-
- Status:
- {{ response.statusCode || $t("waiting_send_req") }}
-
-
- Time:
- {{ `${response.meta.responseDuration} ms` }}
-
-
- Size:
- {{ `${response.meta.responseSize} B` }}
-
+
+
+ {{ $t("waiting_send_req") }}
+
+
+
+ refresh
+
+
+
+ Status:
+ {{ response.statusCode || $t("waiting_send_req") }}
+
+
+ Time:
+ {{ `${response.meta.responseDuration} ms` }}
+
+
+ Size:
+ {{ `${response.meta.responseSize} B` }}
+
+
diff --git a/components/realtime/Mqtt.vue b/components/realtime/Mqtt.vue
index afec01f2b..b6fce79c6 100644
--- a/components/realtime/Mqtt.vue
+++ b/components/realtime/Mqtt.vue
@@ -194,7 +194,7 @@ export default {
this.client = new Paho.Client(
parseUrl.hostname,
parseUrl.port !== "" ? Number(parseUrl.port) : 8081,
- "postwoman"
+ "hoppscotch"
)
this.client.connect({
onSuccess: this.onConnectionSuccess,
diff --git a/helpers/network.ts b/helpers/network.ts
index 2a43d1c0e..7952e3ecf 100644
--- a/helpers/network.ts
+++ b/helpers/network.ts
@@ -51,7 +51,10 @@ export const sendNetworkRequest = (req: any) =>
export function createRESTNetworkRequestStream(
req: EffectiveHoppRESTRequest
): Observable
{
- const response = new BehaviorSubject({ type: "loading" })
+ const response = new BehaviorSubject({
+ type: "loading",
+ req,
+ })
const headers = req.effectiveFinalHeaders.reduce((acc, { key, value }) => {
return Object.assign(acc, { [key]: value })
@@ -60,32 +63,73 @@ export function createRESTNetworkRequestStream(
const timeStart = Date.now()
runAppropriateStrategy({
+ method: req.method as any,
url: req.effectiveFinalURL,
headers,
- }).then((res: any) => {
- const timeEnd = Date.now()
-
- const contentLength = res.headers["content-length"]
- ? parseInt(res.headers["content-length"])
- : (res.data as ArrayBuffer).byteLength
-
- const resObj: HoppRESTResponse = {
- type: "success",
- statusCode: res.status,
- body: res.data,
- headers: Object.keys(res.headers).map((x) => ({
- key: x,
- value: res.headers[x],
- })),
- meta: {
- responseSize: contentLength,
- responseDuration: timeEnd - timeStart,
- },
- }
- response.next(resObj)
-
- response.complete()
})
+ .then((res: any) => {
+ const timeEnd = Date.now()
+
+ const contentLength = res.headers["content-length"]
+ ? parseInt(res.headers["content-length"])
+ : (res.data as ArrayBuffer).byteLength
+
+ const resObj: HoppRESTResponse = {
+ type: "success",
+ statusCode: res.status,
+ body: res.data,
+ headers: Object.keys(res.headers).map((x) => ({
+ key: x,
+ value: res.headers[x],
+ })),
+ meta: {
+ responseSize: contentLength,
+ responseDuration: timeEnd - timeStart,
+ },
+ req,
+ }
+ response.next(resObj)
+
+ response.complete()
+ })
+ .catch((err) => {
+ if (err.response) {
+ const timeEnd = Date.now()
+
+ const contentLength = err.response.headers["content-length"]
+ ? parseInt(err.response.headers["content-length"])
+ : (err.response.data as ArrayBuffer).byteLength
+
+ const resObj: HoppRESTResponse = {
+ type: "fail",
+ body: err.response.data,
+ headers: Object.keys(err.response.headers).map((x) => ({
+ key: x,
+ value: err.response.headers[x],
+ })),
+ meta: {
+ responseDuration: timeEnd - timeStart,
+ responseSize: contentLength,
+ },
+ req,
+ statusCode: err.response.status,
+ }
+
+ response.next(resObj)
+
+ response.complete()
+ } else {
+ const resObj: HoppRESTResponse = {
+ type: "network_fail",
+ error: err,
+ req,
+ }
+
+ response.next(resObj)
+
+ response.complete()
+ }
+ })
return response
}
diff --git a/helpers/types/HoppRESTRequest.ts b/helpers/types/HoppRESTRequest.ts
index cc7148005..9555df4e4 100644
--- a/helpers/types/HoppRESTRequest.ts
+++ b/helpers/types/HoppRESTRequest.ts
@@ -1,3 +1,5 @@
+export const RESTReqSchemaVersion = "1"
+
export type HoppRESTParam = {
key: string
value: string
@@ -11,8 +13,44 @@ export type HoppRESTHeader = {
}
export interface HoppRESTRequest {
+ v: string
+
method: string
endpoint: string
params: HoppRESTParam[]
headers: HoppRESTHeader[]
}
+
+export function isHoppRESTRequest(x: any): x is HoppRESTRequest {
+ return x && typeof x === "object" && "v" in x
+}
+
+export function translateToNewRequest(x: any): HoppRESTRequest {
+ if (isHoppRESTRequest(x)) {
+ return x
+ } else {
+ // Old format
+ const endpoint: string = `${x.url}${x.path}`
+
+ const headers: HoppRESTHeader[] = x.headers
+
+ // Remove old keys from params
+ const params: HoppRESTParam[] = (x.params as any[]).map(
+ ({ key, value, active }) => ({
+ key,
+ value,
+ active,
+ })
+ )
+
+ const method = x.method
+
+ return {
+ endpoint,
+ headers,
+ params,
+ method,
+ v: RESTReqSchemaVersion,
+ }
+ }
+}
diff --git a/helpers/types/HoppRESTResponse.ts b/helpers/types/HoppRESTResponse.ts
index a6f8ec951..90a66a443 100644
--- a/helpers/types/HoppRESTResponse.ts
+++ b/helpers/types/HoppRESTResponse.ts
@@ -1,14 +1,25 @@
+import { HoppRESTRequest } from "./HoppRESTRequest"
+
export type HoppRESTResponse =
- | { type: "loading" }
+ | { type: "loading"; req: HoppRESTRequest }
| {
type: "fail"
headers: { key: string; value: string }[]
body: ArrayBuffer
statusCode: number
+
+ meta: {
+ responseSize: number // in bytes
+ responseDuration: number // in millis
+ }
+
+ req: HoppRESTRequest
}
| {
type: "network_fail"
error: Error
+
+ req: HoppRESTRequest
}
| {
type: "success"
@@ -19,4 +30,6 @@ export type HoppRESTResponse =
responseSize: number // in bytes
responseDuration: number // in millis
}
+
+ req: HoppRESTRequest
}
diff --git a/newstore/RESTSession.ts b/newstore/RESTSession.ts
index 34963c0bd..e9b4a46c8 100644
--- a/newstore/RESTSession.ts
+++ b/newstore/RESTSession.ts
@@ -1,9 +1,10 @@
-import { pluck, distinctUntilChanged, map } from "rxjs/operators"
+import { pluck, distinctUntilChanged, map, filter } from "rxjs/operators"
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
import {
HoppRESTHeader,
HoppRESTParam,
HoppRESTRequest,
+ RESTReqSchemaVersion,
} from "~/helpers/types/HoppRESTRequest"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
@@ -115,6 +116,7 @@ type RESTSession = {
const defaultRESTSession: RESTSession = {
request: {
+ v: RESTReqSchemaVersion,
endpoint: "https://httpbin.org/get",
params: [],
headers: [],
@@ -124,6 +126,11 @@ const defaultRESTSession: RESTSession = {
}
const dispatchers = defineDispatchers({
+ setRequest(_: RESTSession, { req }: { req: HoppRESTRequest }) {
+ return {
+ request: req,
+ }
+ },
setEndpoint(curr: RESTSession, { newEndpoint }: { newEndpoint: string }) {
const paramsInNewURL = getParamsInURL(newEndpoint)
const updatedParams = recalculateParams(
@@ -297,6 +304,15 @@ const dispatchers = defineDispatchers({
const restSessionStore = new DispatchingStore(defaultRESTSession, dispatchers)
+export function setRESTRequest(req: HoppRESTRequest) {
+ restSessionStore.dispatch({
+ dispatcher: "setRequest",
+ payload: {
+ req,
+ },
+ })
+}
+
export function setRESTEndpoint(newEndpoint: string) {
restSessionStore.dispatch({
dispatcher: "setEndpoint",
@@ -438,3 +454,10 @@ export const restResponse$ = restSessionStore.subject$.pipe(
pluck("response"),
distinctUntilChanged()
)
+
+export const completedRESTResponse$ = restResponse$.pipe(
+ filter(
+ (res) =>
+ res !== null && res.type !== "loading" && res.type !== "network_fail"
+ )
+)
diff --git a/newstore/history.ts b/newstore/history.ts
index 3a9f5705a..29a560ef5 100644
--- a/newstore/history.ts
+++ b/newstore/history.ts
@@ -1,6 +1,7 @@
import eq from "lodash/eq"
import { pluck } from "rxjs/operators"
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
+import { completedRESTResponse$ } from "./RESTSession"
export const defaultRESTHistoryState = {
state: [] as any[],
@@ -136,3 +137,18 @@ export function toggleGraphqlHistoryEntryStar(entry: any) {
payload: { entry },
})
}
+
+// Listen to completed responses to add to history
+completedRESTResponse$.subscribe((res) => {
+ if (res !== null) {
+ if (res.type === "loading" || res.type === "network_fail") return
+
+ addRESTHistoryEntry({
+ ...res.req,
+ type: res.type,
+ meta: res.meta,
+ statusCode: res.statusCode,
+ star: false,
+ })
+ }
+})
diff --git a/pages/index.vue b/pages/index.vue
index cc2ac74d3..d6cd2cf00 100644
--- a/pages/index.vue
+++ b/pages/index.vue
@@ -462,11 +462,7 @@