diff --git a/assets/css/styles.scss b/assets/css/styles.scss
index 4d52377b5..7a9d668fe 100644
--- a/assets/css/styles.scss
+++ b/assets/css/styles.scss
@@ -286,6 +286,11 @@ hr {
.info:not(.toasted) {
margin-left: 4px;
color: var(--fg-light-color);
+
+ .material-icons {
+ vertical-align: middle;
+ margin-right: 8px;
+ }
}
.bg-color {
@@ -535,11 +540,6 @@ ol {
padding: 0;
list-style-type: none;
- &.response-headers {
- display: inline-flex;
- width: 50%;
- }
-
ul,
ol {
margin: 0;
diff --git a/components/collections/index.vue b/components/collections/index.vue
index 2aac7dad7..510dbefd7 100644
--- a/components/collections/index.vue
+++ b/components/collections/index.vue
@@ -62,7 +62,7 @@ TODO:
- Create new collection
+ help_outline Create new collection
@@ -76,9 +76,6 @@ TODO:
@edit-request="editRequest($event)"
/>
- -
-
-
diff --git a/components/environments/editEnvironment.vue b/components/environments/editEnvironment.vue
index f269ccd04..7a685111d 100644
--- a/components/environments/editEnvironment.vue
+++ b/components/environments/editEnvironment.vue
@@ -35,14 +35,6 @@
-
@@ -114,13 +106,9 @@
diff --git a/components/lenses/headers.vue b/components/lenses/headers.vue
new file mode 100644
index 000000000..fab9ccbe8
--- /dev/null
+++ b/components/lenses/headers.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/components/lenses/renderers/HTMLLensRenderer.vue b/components/lenses/renderers/HTMLLensRenderer.vue
new file mode 100644
index 000000000..5eb468af0
--- /dev/null
+++ b/components/lenses/renderers/HTMLLensRenderer.vue
@@ -0,0 +1,153 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/lenses/renderers/ImageLensRenderer.vue b/components/lenses/renderers/ImageLensRenderer.vue
new file mode 100644
index 000000000..234ed629b
--- /dev/null
+++ b/components/lenses/renderers/ImageLensRenderer.vue
@@ -0,0 +1,102 @@
+
+
+ -
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
+
diff --git a/components/lenses/renderers/JSONLensRenderer.vue b/components/lenses/renderers/JSONLensRenderer.vue
new file mode 100644
index 000000000..ebbba2cb6
--- /dev/null
+++ b/components/lenses/renderers/JSONLensRenderer.vue
@@ -0,0 +1,149 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
+
error_outline Invalid JSON
+
+
+
+
+
+
+
+
+
diff --git a/components/lenses/renderers/RawLensRenderer.vue b/components/lenses/renderers/RawLensRenderer.vue
new file mode 100644
index 000000000..12ab9642d
--- /dev/null
+++ b/components/lenses/renderers/RawLensRenderer.vue
@@ -0,0 +1,134 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/lenses/renderers/XMLLensRenderer.vue b/components/lenses/renderers/XMLLensRenderer.vue
new file mode 100644
index 000000000..8738027c1
--- /dev/null
+++ b/components/lenses/renderers/XMLLensRenderer.vue
@@ -0,0 +1,125 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/lenses/renderers/mixins/TextContentRendererMixin.js b/components/lenses/renderers/mixins/TextContentRendererMixin.js
new file mode 100644
index 000000000..30f31f517
--- /dev/null
+++ b/components/lenses/renderers/mixins/TextContentRendererMixin.js
@@ -0,0 +1,10 @@
+export default {
+ props: {
+ response: {},
+ },
+ computed: {
+ responseBodyText() {
+ return new TextDecoder("utf-8").decode(this.response.body)
+ },
+ },
+}
diff --git a/directives/textareaAutoHeight.js b/directives/textareaAutoHeight.js
deleted file mode 100644
index 7f64a4784..000000000
--- a/directives/textareaAutoHeight.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
- name: "textareaAutoHeight",
- update({ scrollHeight, clientHeight, style }) {
- if (scrollHeight !== clientHeight) {
- style.minHeight = `${scrollHeight}px`
- }
- },
-}
diff --git a/helpers/lenses/htmlLens.js b/helpers/lenses/htmlLens.js
new file mode 100644
index 000000000..5a8e3244d
--- /dev/null
+++ b/helpers/lenses/htmlLens.js
@@ -0,0 +1,8 @@
+const htmlLens = {
+ lensName: "HTML",
+ supportedContentTypes: ["text/html"],
+ renderer: "htmlres",
+ rendererImport: () => import("~/components/lenses/renderers/HTMLLensRenderer"),
+}
+
+export default htmlLens
diff --git a/helpers/lenses/imageLens.js b/helpers/lenses/imageLens.js
new file mode 100644
index 000000000..1153822a4
--- /dev/null
+++ b/helpers/lenses/imageLens.js
@@ -0,0 +1,16 @@
+const imageLens = {
+ lensName: "Image",
+ supportedContentTypes: [
+ "image/gif",
+ "image/jpeg",
+ "image/png",
+ "image/bmp",
+ "image/svg+xml",
+ "image/x-icon",
+ "image/vnd.microsoft.icon",
+ ],
+ renderer: "imageres",
+ rendererImport: () => import("~/components/lenses/renderers/ImageLensRenderer"),
+}
+
+export default imageLens
diff --git a/helpers/lenses/jsonLens.js b/helpers/lenses/jsonLens.js
new file mode 100644
index 000000000..5c337c1aa
--- /dev/null
+++ b/helpers/lenses/jsonLens.js
@@ -0,0 +1,8 @@
+const jsonLens = {
+ lensName: "JSON",
+ supportedContentTypes: ["application/json", "application/hal+json", "application/vnd.api+json"],
+ renderer: "json",
+ rendererImport: () => import("~/components/lenses/renderers/JSONLensRenderer"),
+}
+
+export default jsonLens
diff --git a/helpers/lenses/lenses.js b/helpers/lenses/lenses.js
new file mode 100644
index 000000000..6423bcf10
--- /dev/null
+++ b/helpers/lenses/lenses.js
@@ -0,0 +1,37 @@
+import jsonLens from "./jsonLens"
+import rawLens from "./rawLens"
+import imageLens from "./imageLens"
+import htmlLens from "./htmlLens"
+import xmlLens from "./xmlLens"
+
+const lenses = [jsonLens, imageLens, htmlLens, xmlLens, rawLens]
+
+export function getSuitableLenses(response) {
+ const result = []
+
+ if (response && response.headers && response.headers["content-type"]) {
+ const properContentType = response.headers["content-type"].split(";")[0]
+
+ for (const lens of lenses) {
+ if (
+ lens.supportedContentTypes === null ||
+ lens.supportedContentTypes.includes(properContentType)
+ ) {
+ result.push(lens)
+ }
+ }
+ } else {
+ // We don't know the content type, so lets just add rawLens
+ result.push(rawLens)
+ }
+
+ return result
+}
+
+export function getLensRenderers() {
+ const response = {}
+ for (const lens of lenses) {
+ response[lens.renderer] = lens.rendererImport
+ }
+ return response
+}
diff --git a/helpers/lenses/rawLens.js b/helpers/lenses/rawLens.js
new file mode 100644
index 000000000..2bb9635d4
--- /dev/null
+++ b/helpers/lenses/rawLens.js
@@ -0,0 +1,8 @@
+const rawLens = {
+ lensName: "Raw",
+ supportedContentTypes: null,
+ renderer: "raw",
+ rendererImport: () => import("~/components/lenses/renderers/RawLensRenderer"),
+}
+
+export default rawLens
diff --git a/helpers/lenses/xmlLens.js b/helpers/lenses/xmlLens.js
new file mode 100644
index 000000000..eb0b5a60b
--- /dev/null
+++ b/helpers/lenses/xmlLens.js
@@ -0,0 +1,8 @@
+const xmlLens = {
+ lensName: "XML",
+ supportedContentTypes: ["application/xml", "image/svg+xml", "text/xml", "application/rss+xml"],
+ renderer: "xmlres",
+ rendererImport: () => import("~/components/lenses/renderers/XMLLensRenderer"),
+}
+
+export default xmlLens
diff --git a/helpers/strategies/AxiosStrategy.js b/helpers/strategies/AxiosStrategy.js
index 81361009f..583cdcd19 100644
--- a/helpers/strategies/AxiosStrategy.js
+++ b/helpers/strategies/AxiosStrategy.js
@@ -1,4 +1,5 @@
import axios from "axios"
+import { decodeB64StringToArrayBuffer } from "../utils/b64"
let cancelSource = axios.CancelToken.source()
@@ -13,11 +14,19 @@ const axiosWithProxy = async (req, { state }) => {
try {
const { data } = await axios.post(
state.postwoman.settings.PROXY_URL || "https://postwoman.apollosoftware.xyz/",
- req,
+ {
+ ...req,
+ wantsBinary: true,
+ },
{
cancelToken: cancelSource.token,
}
)
+
+ if (data.isBinary) {
+ data.data = decodeB64StringToArrayBuffer(data.data)
+ }
+
return data
} catch (e) {
// Check if the throw is due to a cancellation
@@ -34,28 +43,9 @@ const axiosWithoutProxy = async (req, _store) => {
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
- },
- ],
+ responseType: "arraybuffer",
})
+
return res
} catch (e) {
if (axios.isCancel(e)) {
diff --git a/helpers/strategies/ExtensionStrategy.js b/helpers/strategies/ExtensionStrategy.js
index 2d09c1a88..c98204c35 100644
--- a/helpers/strategies/ExtensionStrategy.js
+++ b/helpers/strategies/ExtensionStrategy.js
@@ -1,3 +1,5 @@
+import { decodeB64StringToArrayBuffer } from "../utils/b64"
+
export const hasExtensionInstalled = () =>
typeof window.__POSTWOMAN_EXTENSION_HOOK__ !== "undefined"
@@ -17,13 +19,24 @@ const extensionWithProxy = async (req, { state }) => {
const { data } = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
method: "post",
url: state.postwoman.settings.PROXY_URL || "https://postwoman.apollosoftware.xyz/",
- data: req,
+ data: {
+ ...req,
+ wantsBinary: true,
+ },
})
+
+ if (data.isBinary) {
+ data.data = decodeB64StringToArrayBuffer(data.data)
+ }
+
return data
}
const extensionWithoutProxy = async (req, _store) => {
- const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest(req)
+ const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
+ ...req,
+ wantsBinary: true,
+ })
return res
}
diff --git a/helpers/utils/b64.js b/helpers/utils/b64.js
new file mode 100644
index 000000000..51869b6d2
--- /dev/null
+++ b/helpers/utils/b64.js
@@ -0,0 +1,31 @@
+export const decodeB64StringToArrayBuffer = (input) => {
+ const bytes = Math.floor((input.length / 4) * 3)
+ const ab = new ArrayBuffer(bytes)
+ const uarray = new Uint8Array(ab)
+
+ const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
+
+ let chr1, chr2, chr3
+ let enc1, enc2, enc3, enc4
+ let j = 0
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "")
+
+ for (let i = 0; i < bytes; i += 3) {
+ //get the 3 octets in 4 ASCII chars
+ enc1 = keyStr.indexOf(input.charAt(j++))
+ enc2 = keyStr.indexOf(input.charAt(j++))
+ enc3 = keyStr.indexOf(input.charAt(j++))
+ enc4 = keyStr.indexOf(input.charAt(j++))
+
+ chr1 = (enc1 << 2) | (enc2 >> 4)
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2)
+ chr3 = ((enc3 & 3) << 6) | enc4
+
+ uarray[i] = chr1
+ if (enc3 != 64) uarray[i + 1] = chr2
+ if (enc4 != 64) uarray[i + 2] = chr3
+ }
+
+ return ab
+}
diff --git a/lang/en-US.json b/lang/en-US.json
index ae614543e..581067878 100644
--- a/lang/en-US.json
+++ b/lang/en-US.json
@@ -285,5 +285,7 @@
"mqtt_topic_title": "Publish / Subscribe topic",
"mqtt_publish": "Publish",
"mqtt_subscribe": "Subscribe",
- "mqtt_unsubscribe": "Unsubscribe"
+ "mqtt_unsubscribe": "Unsubscribe",
+ "pre_request_script": "Pre-request Script",
+ "tests": "Tests"
}
diff --git a/pages/graphql.vue b/pages/graphql.vue
index 7c77e8086..a097110a6 100644
--- a/pages/graphql.vue
+++ b/pages/graphql.vue
@@ -27,7 +27,7 @@
-