Merge pull request #915 from AndrewBastin/feat/cancel-button
Cancellable Requests
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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?",
|
||||
|
||||
128
pages/index.vue
128
pages/index.vue
@@ -189,12 +189,25 @@
|
||||
</li>
|
||||
<li class="shrink">
|
||||
<label class="hide-on-small-screen" for="send"> </label>
|
||||
<button :disabled="!isValidURL" @click="sendRequest" id="send" ref="sendButton">
|
||||
<button
|
||||
v-if="!runningRequest"
|
||||
:disabled="!isValidURL"
|
||||
@click="sendRequest"
|
||||
id="send"
|
||||
ref="sendButton"
|
||||
>
|
||||
{{ $t("send") }}
|
||||
<span>
|
||||
<i class="material-icons">send</i>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button v-else @click="cancelRequest" id="send" ref="sendButton">
|
||||
{{ $t("cancel") }}
|
||||
<span>
|
||||
<i class="material-icons">clear</i>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="blue">
|
||||
@@ -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" })
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user