Accurate response time and size (#1441)
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
@@ -672,7 +672,7 @@ ol li {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.missing-data-response {
|
.missing-data-response {
|
||||||
@apply bg-errColor;
|
@apply text-fgLightColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
#response-details-wrapper {
|
#response-details-wrapper {
|
||||||
|
|||||||
47
components/http/http-response-meta.vue
Normal file
47
components/http/http-response-meta.vue
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<label>{{ $t("response") }}</label>
|
||||||
|
<label v-if="active"><i class="animate-spin material-icons">refresh</i></label>
|
||||||
|
<label v-else :class="statusCategory ? statusCategory.className : ''">
|
||||||
|
<i class="material-icons">fiber_manual_record</i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col lg:flex-row">
|
||||||
|
<label class="flex-1">
|
||||||
|
{{ $t("status") + `: \xA0 ` }}
|
||||||
|
<span :class="statusCategory ? statusCategory.className : ''">
|
||||||
|
{{ response.status || $t("waiting_send_req") }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
{{ $t("duration") + `: \xA0 ${response.duration} ms` }}
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
{{ $t("size") + `: \xA0 ${response.size} B` }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import findStatusGroup from "~/helpers/findStatusGroup"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
response: {
|
||||||
|
type: Object,
|
||||||
|
default: {},
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
statusCategory() {
|
||||||
|
return findStatusGroup(this.response.status)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
23
components/http/http-response.vue
Normal file
23
components/http/http-response.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<pw-section class="purple" id="response" :label="$t('response')" ref="response" no-legend>
|
||||||
|
<http-response-meta :response="response" :active="active" />
|
||||||
|
<div v-if="response.body && response.body !== $t('loading')">
|
||||||
|
<response-body-renderer :response="response" />
|
||||||
|
</div>
|
||||||
|
</pw-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
response: {
|
||||||
|
type: Object,
|
||||||
|
default: {},
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<label for="body">{{ $t("response") }}</label>
|
<label for="body">{{ $t("response_body") }}</label>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="icon"
|
class="icon"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<label for="body">{{ $t("response") }}</label>
|
<label for="body">{{ $t("response_body") }}</label>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="icon"
|
class="icon"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<label for="body">{{ $t("response") }}</label>
|
<label for="body">{{ $t("response_body") }}</label>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="icon"
|
class="icon"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<label for="body">{{ $t("response") }}</label>
|
<label for="body">{{ $t("response_body") }}</label>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="icon"
|
class="icon"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<label for="body">{{ $t("response") }}</label>
|
<label for="body">{{ $t("response_body") }}</label>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="icon"
|
class="icon"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tabs-wrapper">
|
<div class="tabs-wrapper">
|
||||||
<div class="tabs">
|
<div class="tabs" :class="styles">
|
||||||
<ul :class="styles">
|
<ul>
|
||||||
<li
|
<li
|
||||||
v-for="(tab, index) in tabs"
|
v-for="(tab, index) in tabs"
|
||||||
:class="{ 'is-active': tab.isActive }"
|
:class="{ 'is-active': tab.isActive }"
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { decodeB64StringToArrayBuffer } from "../utils/b64"
|
import { decodeB64StringToArrayBuffer } from "../utils/b64"
|
||||||
|
|
||||||
|
axios.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
config.timeData = { startTime: new Date().getTime() }
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
axios.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
response.config.timeData.endTime = new Date().getTime()
|
||||||
|
return response
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
let cancelSource = axios.CancelToken.source()
|
let cancelSource = axios.CancelToken.source()
|
||||||
|
|
||||||
export const cancelRunningAxiosRequest = () => {
|
export const cancelRunningAxiosRequest = () => {
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ export const cancelRunningExtensionRequest = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const extensionWithProxy = async (req, { state }) => {
|
const extensionWithProxy = async (req, { state }) => {
|
||||||
const { data } = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
const backupTimeDataStart = new Date().getTime();
|
||||||
|
|
||||||
|
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
||||||
method: "post",
|
method: "post",
|
||||||
url: state.postwoman.settings.PROXY_URL || "https://hoppscotch.apollosoftware.xyz/",
|
url: state.postwoman.settings.PROXY_URL || "https://hoppscotch.apollosoftware.xyz/",
|
||||||
data: {
|
data: {
|
||||||
@@ -25,7 +27,9 @@ const extensionWithProxy = async (req, { state }) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const parsedData = JSON.parse(data)
|
const backupTimeDataEnd = new Date().getTime();
|
||||||
|
|
||||||
|
const parsedData = JSON.parse(res.data)
|
||||||
|
|
||||||
if (!parsedData.success) {
|
if (!parsedData.success) {
|
||||||
throw new Error(parsedData.data.message || "Proxy Error")
|
throw new Error(parsedData.data.message || "Proxy Error")
|
||||||
@@ -35,14 +39,38 @@ const extensionWithProxy = async (req, { state }) => {
|
|||||||
parsedData.data = decodeB64StringToArrayBuffer(parsedData.data)
|
parsedData.data = decodeB64StringToArrayBuffer(parsedData.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(res && res.config && res.config.timeData)) {
|
||||||
|
res.config = {
|
||||||
|
timeData: {
|
||||||
|
startTime: backupTimeDataStart,
|
||||||
|
endTime: backupTimeDataEnd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedData.config = res.config
|
||||||
|
|
||||||
return parsedData
|
return parsedData
|
||||||
}
|
}
|
||||||
|
|
||||||
const extensionWithoutProxy = async (req, _store) => {
|
const extensionWithoutProxy = async (req, _store) => {
|
||||||
|
const backupTimeDataStart = new Date().getTime();
|
||||||
|
|
||||||
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
|
||||||
...req,
|
...req,
|
||||||
wantsBinary: true,
|
wantsBinary: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const backupTimeDataEnd = new Date().getTime();
|
||||||
|
|
||||||
|
if (!(res && res.config && res.config.timeData)) {
|
||||||
|
res.config = {
|
||||||
|
timeData: {
|
||||||
|
startTime: backupTimeDataStart,
|
||||||
|
endTime: backupTimeDataEnd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
"parameter_list": "Parameter List",
|
"parameter_list": "Parameter List",
|
||||||
"request_body": "Request Body",
|
"request_body": "Request Body",
|
||||||
"raw_request_body": "Raw Request Body",
|
"raw_request_body": "Raw Request Body",
|
||||||
|
"response_body": "Response Body",
|
||||||
"show_code": "Show Code",
|
"show_code": "Show Code",
|
||||||
"show_prerequest_script": "Show Pre-Request Script",
|
"show_prerequest_script": "Show Pre-Request Script",
|
||||||
"hide_prerequest_script": "Hide Pre-Request Script",
|
"hide_prerequest_script": "Hide Pre-Request Script",
|
||||||
@@ -301,5 +302,6 @@
|
|||||||
"enter_gist_url": "Enter Gist URL",
|
"enter_gist_url": "Enter Gist URL",
|
||||||
"account_exists": "Account exists with different credential - Login to link both accounts",
|
"account_exists": "Account exists with different credential - Login to link both accounts",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"new_version_found": "New version found. Refresh to update."
|
"new_version_found": "New version found. Refresh to update.",
|
||||||
|
"size": "Size"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,7 +266,7 @@
|
|||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<label>{{ $t("response") }}</label>
|
<label>{{ $t("response") }}</label>
|
||||||
<div class="row-wrapper">
|
<div class="row-wrapper">
|
||||||
<label for="responseField">{{ $t("response") }}</label>
|
<label for="responseField">{{ $t("response_body") }}</label>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
class="icon"
|
class="icon"
|
||||||
|
|||||||
@@ -590,28 +590,7 @@
|
|||||||
</tabs>
|
</tabs>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<pw-section class="purple" id="response" :label="$t('response')" ref="response">
|
<http-response :response="response" :active="runningRequest" ref="response" />
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<label for="status">{{ $t("status") }}</label>
|
|
||||||
<input
|
|
||||||
:class="[
|
|
||||||
statusCategory ? statusCategory.className : '',
|
|
||||||
response.status ? '' : 'rounded-b-lg',
|
|
||||||
]"
|
|
||||||
:value="response.status || $t('waiting_send_req')"
|
|
||||||
ref="status"
|
|
||||||
id="status"
|
|
||||||
name="status"
|
|
||||||
readonly
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<div v-if="response.body && response.body !== $t('loading')">
|
|
||||||
<response-body-renderer :response="response" />
|
|
||||||
</div>
|
|
||||||
</pw-section>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<aside v-if="activeSidebar" class="sticky-inner inner-right lg:max-w-md">
|
<aside v-if="activeSidebar" class="sticky-inner inner-right lg:max-w-md">
|
||||||
@@ -752,7 +731,6 @@ import { parseUrlAndPath } from "~/helpers/utils/uri"
|
|||||||
import { httpValid } from "~/helpers/utils/valid"
|
import { httpValid } from "~/helpers/utils/valid"
|
||||||
import { knownContentTypes, isJSONContentType } from "~/helpers/utils/contenttypes"
|
import { knownContentTypes, isJSONContentType } from "~/helpers/utils/contenttypes"
|
||||||
import { generateCodeWithGenerator } from "~/helpers/codegen/codegen"
|
import { generateCodeWithGenerator } from "~/helpers/codegen/codegen"
|
||||||
import findStatusGroup from "~/helpers/findStatusGroup"
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -771,6 +749,8 @@ export default {
|
|||||||
status: "",
|
status: "",
|
||||||
headers: "",
|
headers: "",
|
||||||
body: "",
|
body: "",
|
||||||
|
duration: 0,
|
||||||
|
size: 0,
|
||||||
},
|
},
|
||||||
validContentTypes: knownContentTypes,
|
validContentTypes: knownContentTypes,
|
||||||
paramsWatchEnabled: true,
|
paramsWatchEnabled: true,
|
||||||
@@ -1174,9 +1154,6 @@ export default {
|
|||||||
requestName() {
|
requestName() {
|
||||||
return this.name
|
return this.name
|
||||||
},
|
},
|
||||||
statusCategory() {
|
|
||||||
return findStatusGroup(this.response.status)
|
|
||||||
},
|
|
||||||
isValidURL() {
|
isValidURL() {
|
||||||
// if showPreRequestScript, we cannot determine if a URL is valid because the full string is not known ahead of time
|
// if showPreRequestScript, we cannot determine if a URL is valid because the full string is not known ahead of time
|
||||||
return this.showPreRequestScript || httpValid(this.url)
|
return this.showPreRequestScript || httpValid(this.url)
|
||||||
@@ -1365,9 +1342,12 @@ export default {
|
|||||||
// Start showing the loading bar as soon as possible.
|
// Start showing the loading bar as soon as possible.
|
||||||
// The nuxt axios module will hide it when the request is made.
|
// The nuxt axios module will hide it when the request is made.
|
||||||
this.$nuxt.$loading.start()
|
this.$nuxt.$loading.start()
|
||||||
this.previewEnabled = false
|
this.response = {
|
||||||
this.response.status = this.$t("fetching")
|
duration: 0,
|
||||||
this.response.body = this.$t("loading")
|
size: 0,
|
||||||
|
status: this.$t("fetching"),
|
||||||
|
body: this.$t("loading"),
|
||||||
|
}
|
||||||
const auth =
|
const auth =
|
||||||
this.auth === "Basic Auth"
|
this.auth === "Basic Auth"
|
||||||
? {
|
? {
|
||||||
@@ -1421,8 +1401,6 @@ export default {
|
|||||||
})
|
})
|
||||||
headers = headersObject
|
headers = headersObject
|
||||||
try {
|
try {
|
||||||
const startTime = Date.now()
|
|
||||||
|
|
||||||
this.runningRequest = true
|
this.runningRequest = true
|
||||||
const payload = await this.makeRequest(
|
const payload = await this.makeRequest(
|
||||||
auth,
|
auth,
|
||||||
@@ -1431,11 +1409,9 @@ export default {
|
|||||||
this.showPreRequestScript && this.preRequestScript
|
this.showPreRequestScript && this.preRequestScript
|
||||||
)
|
)
|
||||||
this.runningRequest = false
|
this.runningRequest = false
|
||||||
|
const duration = payload.config.timeData.endTime - payload.config.timeData.startTime
|
||||||
const duration = Date.now() - startTime
|
this.response.duration = duration
|
||||||
this.$toast.info(this.$t("finished_in", { duration }), {
|
this.response.size = payload.headers["content-length"]
|
||||||
icon: "done",
|
|
||||||
})
|
|
||||||
;(() => {
|
;(() => {
|
||||||
this.response.status = payload.status
|
this.response.status = payload.status
|
||||||
this.response.headers = payload.headers
|
this.response.headers = payload.headers
|
||||||
|
|||||||
Reference in New Issue
Block a user