diff --git a/functions/network.js b/functions/network.js
index c58cc7fd1..5b45cc31c 100644
--- a/functions/network.js
+++ b/functions/network.js
@@ -1,5 +1,16 @@
-import AxiosStrategy from "./strategies/AxiosStrategy"
-import ExtensionStrategy, { hasExtensionInstalled } from "./strategies/ExtensionStrategy"
+import AxiosStrategy, { cancelRunningAxiosRequest } from "./strategies/AxiosStrategy"
+import ExtensionStrategy, {
+ cancelRunningExtensionRequest,
+ hasExtensionInstalled,
+} from "./strategies/ExtensionStrategy"
+
+export const cancelRunningRequest = (store) => {
+ if (isExtensionsAllowed(store) && hasExtensionInstalled()) {
+ cancelRunningExtensionRequest()
+ } else {
+ cancelRunningAxiosRequest()
+ }
+}
const isExtensionsAllowed = ({ state }) =>
typeof state.postwoman.settings.EXTENSIONS_ENABLED === "undefined" ||
@@ -13,7 +24,5 @@ const runAppropriateStrategy = (req, store) => {
return AxiosStrategy(req, store)
}
-const sendNetworkRequest = (req, store) =>
+export const sendNetworkRequest = (req, store) =>
runAppropriateStrategy(req, store).finally(() => window.$nuxt.$loading.finish())
-
-export { sendNetworkRequest }
diff --git a/functions/strategies/AxiosStrategy.js b/functions/strategies/AxiosStrategy.js
index 1deda3333..81361009f 100644
--- a/functions/strategies/AxiosStrategy.js
+++ b/functions/strategies/AxiosStrategy.js
@@ -1,39 +1,69 @@
import axios from "axios"
+let cancelSource = axios.CancelToken.source()
+
+export const cancelRunningAxiosRequest = () => {
+ cancelSource.cancel()
+
+ // Create a new cancel token
+ cancelSource = axios.CancelToken.source()
+}
+
const axiosWithProxy = async (req, { state }) => {
- const { data } = await axios.post(
- state.postwoman.settings.PROXY_URL || "https://postwoman.apollosoftware.xyz/",
- req
- )
- return data
+ try {
+ const { data } = await axios.post(
+ state.postwoman.settings.PROXY_URL || "https://postwoman.apollosoftware.xyz/",
+ req,
+ {
+ cancelToken: cancelSource.token,
+ }
+ )
+ return data
+ } catch (e) {
+ // Check if the throw is due to a cancellation
+ if (axios.isCancel(e)) {
+ throw "cancellation"
+ } else {
+ throw e
+ }
+ }
}
const axiosWithoutProxy = async (req, _store) => {
- const res = await axios({
- ...req,
- transformResponse: [
- (data, headers) => {
- // If the response has a JSON content type, try parsing it
- if (
- headers["content-type"] &&
- (headers["content-type"].startsWith("application/json") ||
- headers["content-type"].startsWith("application/vnd.api+json") ||
- headers["content-type"].startsWith("application/hal+json"))
- ) {
- try {
- const jsonData = JSON.parse(data)
- return jsonData
- } catch (e) {
- return data
+ try {
+ const res = await axios({
+ ...req,
+ cancelToken: cancelSource.token,
+ transformResponse: [
+ (data, headers) => {
+ // If the response has a JSON content type, try parsing it
+ if (
+ headers["content-type"] &&
+ (headers["content-type"].startsWith("application/json") ||
+ headers["content-type"].startsWith("application/vnd.api+json") ||
+ headers["content-type"].startsWith("application/hal+json"))
+ ) {
+ try {
+ const jsonData = JSON.parse(data)
+ return jsonData
+ } catch (e) {
+ return data
+ }
}
- }
- // Else return the string itself without any transformations
- return data
- },
- ],
- })
- return res
+ // Else return the string itself without any transformations
+ return data
+ },
+ ],
+ })
+ return res
+ } catch (e) {
+ if (axios.isCancel(e)) {
+ throw "cancellation"
+ } else {
+ throw e
+ }
+ }
}
const axiosStrategy = (req, store) => {
diff --git a/functions/strategies/ExtensionStrategy.js b/functions/strategies/ExtensionStrategy.js
index bfea02235..2d09c1a88 100644
--- a/functions/strategies/ExtensionStrategy.js
+++ b/functions/strategies/ExtensionStrategy.js
@@ -7,6 +7,12 @@ export const hasChromeExtensionInstalled = () =>
export const hasFirefoxExtensionInstalled = () =>
hasExtensionInstalled() && /Firefox/i.test(navigator.userAgent)
+export const cancelRunningExtensionRequest = () => {
+ if (hasExtensionInstalled() && window.__POSTWOMAN_EXTENSION_HOOK__.cancelRunningRequest) {
+ window.__POSTWOMAN_EXTENSION_HOOK__.cancelRunningRequest()
+ }
+}
+
const extensionWithProxy = async (req, { state }) => {
const { data } = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
method: "post",
diff --git a/lang/en-US.json b/lang/en-US.json
index 70ab9151f..492cefafe 100644
--- a/lang/en-US.json
+++ b/lang/en-US.json
@@ -187,6 +187,7 @@
"json_prettify_invalid_body": "Couldn't prettify an invalid body, solve json syntax errors and try again",
"prettify_body": "Prettify body",
"cancel": "Cancel",
+ "cancelled": "Cancelled",
"save": "Save",
"dismiss": "Dismiss",
"are_you_sure": "Are you sure?",
diff --git a/pages/index.vue b/pages/index.vue
index 84de058f6..f74cfef23 100644
--- a/pages/index.vue
+++ b/pages/index.vue
@@ -189,12 +189,25 @@
-
@@ -1332,7 +1345,7 @@ import runTestScriptWithVariables from "../functions/postwomanTesting"
import parseTemplateString from "../functions/templating"
import AceEditor from "../components/ui/ace-editor"
import { tokenRequest, oauthRedirect } from "../assets/js/oauth"
-import { sendNetworkRequest } from "../functions/network"
+import { cancelRunningRequest, sendNetworkRequest } from "../functions/network"
import { fb } from "../functions/fb"
import { getEditorLangForMimeType } from "~/functions/editorutils"
import {
@@ -1450,6 +1463,7 @@ export default {
files: [],
filenames: "",
navigatorShare: navigator.share,
+ runningRequest: false,
settings: {
SCROLL_INTO_ENABLED:
@@ -2085,6 +2099,9 @@ export default {
}
return await sendNetworkRequest(requestOptions, this.$store)
},
+ cancelRequest() {
+ cancelRunningRequest(this.$store)
+ },
async sendRequest() {
this.$toast.clear()
if (this.settings.SCROLL_INTO_ENABLED) this.scrollInto("response")
@@ -2154,12 +2171,16 @@ export default {
headers = headersObject
try {
const startTime = Date.now()
+
+ this.runningRequest = true
const payload = await this.makeRequest(
auth,
headers,
requestBody,
this.showPreRequestScript && this.preRequestScript
)
+ this.runningRequest = false
+
const duration = Date.now() - startTime
this.$toast.info(this.$t("finished_in", { duration }), {
icon: "done",
@@ -2202,55 +2223,66 @@ export default {
}
})()
} catch (error) {
- console.log(error)
- if (error.response) {
- this.response.headers = error.response.headers
- this.response.status = error.response.status
- this.response.body = error.response.data
- // Addition of an entry to the history component.
- const entry = {
- label: this.requestName,
- status: this.response.status,
- date: new Date().toLocaleDateString(),
- time: new Date().toLocaleTimeString(),
- method: this.method,
- url: this.url,
- path: this.path,
- usesScripts: Boolean(this.preRequestScript),
- preRequestScript: this.preRequestScript,
- }
+ this.runningRequest = false
- if ((this.preRequestScript && this.showPreRequestScript) || hasPathParams(this.params)) {
- let environmentVariables = getEnvironmentVariablesFromScript(this.preRequestScript)
- environmentVariables = addPathParamsToVariables(this.params, environmentVariables)
- entry.path = parseTemplateString(entry.path, environmentVariables)
- entry.url = parseTemplateString(entry.url, environmentVariables)
- }
-
- this.$refs.historyComponent.addEntry(entry)
- if (fb.currentUser !== null) {
- if (fb.currentSettings[2].value) {
- fb.writeHistory(entry)
- }
- }
- return
+ // If the error is caused by cancellation, do nothing
+ if (error === "cancellation") {
+ this.response.status = this.$t("cancelled")
+ this.response.body = this.$t("cancelled")
} else {
- this.response.status = error.message
- this.response.body = `${error}. ${this.$t("check_console_details")}`
- this.$toast.error(`${error} ${this.$t("f12_details")}`, {
- icon: "error",
- })
- if (!this.$store.state.postwoman.settings.PROXY_ENABLED) {
- this.$toast.info(this.$t("enable_proxy"), {
- icon: "help",
- duration: 8000,
- action: {
- text: this.$t("yes"),
- onClick: (e, toastObject) => {
- this.$router.push({ path: "/settings" })
- },
- },
+ console.log(error)
+ if (error.response) {
+ this.response.headers = error.response.headers
+ this.response.status = error.response.status
+ this.response.body = error.response.data
+ // Addition of an entry to the history component.
+ const entry = {
+ label: this.requestName,
+ status: this.response.status,
+ date: new Date().toLocaleDateString(),
+ time: new Date().toLocaleTimeString(),
+ method: this.method,
+ url: this.url,
+ path: this.path,
+ usesScripts: Boolean(this.preRequestScript),
+ preRequestScript: this.preRequestScript,
+ }
+
+ if (
+ (this.preRequestScript && this.showPreRequestScript) ||
+ hasPathParams(this.params)
+ ) {
+ let environmentVariables = getEnvironmentVariablesFromScript(this.preRequestScript)
+ environmentVariables = addPathParamsToVariables(this.params, environmentVariables)
+ entry.path = parseTemplateString(entry.path, environmentVariables)
+ entry.url = parseTemplateString(entry.url, environmentVariables)
+ }
+
+ this.$refs.historyComponent.addEntry(entry)
+ if (fb.currentUser !== null) {
+ if (fb.currentSettings[2].value) {
+ fb.writeHistory(entry)
+ }
+ }
+ return
+ } else {
+ this.response.status = error.message
+ this.response.body = `${error}. ${this.$t("check_console_details")}`
+ this.$toast.error(`${error} ${this.$t("f12_details")}`, {
+ icon: "error",
})
+ if (!this.$store.state.postwoman.settings.PROXY_ENABLED) {
+ this.$toast.info(this.$t("enable_proxy"), {
+ icon: "help",
+ duration: 8000,
+ action: {
+ text: this.$t("yes"),
+ onClick: (e, toastObject) => {
+ this.$router.push({ path: "/settings" })
+ },
+ },
+ })
+ }
}
}
}