From 065bcbb49bb8efcd5bbb4052f268fa272f93d2f3 Mon Sep 17 00:00:00 2001 From: dyoganan_ford Date: Mon, 8 Sep 2025 20:42:55 +0530 Subject: [PATCH 1/4] Sync devenbap and forked version - Commit includes ford specific changes, allow redirect, auto supression, graphql interceptor issue fix --- packages/hoppscotch-cli/package.json | 4 +- .../collections/digest-auth-success-coll.json | 2 +- .../e2e/fixtures/collections/sample-coll.json | 4 +- .../hoppscotch-cli/src/utils/collections.ts | 11 +- packages/hoppscotch-cli/src/utils/mutators.ts | 19 +- .../hoppscotch-cli/src/utils/pre-request.ts | 10 +- packages/hoppscotch-cli/src/utils/request.ts | 10 +- packages/hoppscotch-common/locales/en.json | 1 + .../src/components/app/Footer.vue | 4 +- .../src/components/app/Header.vue | 5 +- .../src/components/app/KernelInterceptor.vue | 1 + .../src/components/collections/Request.vue | 20 +- .../src/components/http/Request.vue | 2 +- .../src/components/http/Sidebar.vue | 2 +- .../src/components/http/TabHead.vue | 3 +- .../interceptors/ErrorPlaceholder.vue | 96 +++-- .../src/components/settings/Native.vue | 15 + .../src/components/settings/Proxy.vue | 4 +- .../src/helpers/RequestRunner.ts | 2 + .../src/helpers/functional/domain-settings.ts | 2 +- .../src/helpers/functional/process-request.ts | 25 +- .../src/helpers/graphql/connection.ts | 4 + .../src/helpers/kernel/gql/request.ts | 4 + .../src/helpers/kernel/rest/request.ts | 8 +- .../src/helpers/terndoc/pw-test.json | 9 +- .../src/helpers/testSnippets.ts | 7 + .../hoppscotch-common/src/kernel/relay.ts | 9 +- .../src/newstore/settings.ts | 2 + .../hoppscotch-common/src/pages/settings.vue | 11 +- .../src/platform/std/interceptors/proxy.ts | 4 +- .../std/kernel-interceptors/browser/index.ts | 4 +- .../kernel-interceptors/extension/index.ts | 19 +- .../std/kernel-interceptors/native/index.ts | 2 + .../std/kernel-interceptors/native/store.ts | 33 +- .../std/kernel-interceptors/proxy/index.ts | 10 +- .../services/kernel-interceptor.service.ts | 4 +- .../spotlight/searchers/request.searcher.ts | 2 +- .../src/types/post-request.d.ts | 4 + .../plugin-workspace/relay/src/interop.rs | 1 + .../plugin-workspace/relay/src/request.rs | 56 +-- .../tauri-plugin-relay/Cargo.toml | 2 +- .../tauri-plugin-relay/dist-js/index.d.ts | 2 + .../tauri-plugin-relay/dist-js/index.d.ts.map | 2 +- .../tauri-plugin-relay/guest-js/index.ts | 3 + .../hoppscotch-desktop/src-tauri/Cargo.lock | 4 +- .../hoppscotch-desktop/src-tauri/Cargo.toml | 4 +- .../hoppscotch-desktop/src-tauri/src/lib.rs | 3 - .../src-tauri/tauri.conf.json | 4 +- .../hoppscotch-desktop/src/utils/updater.ts | 20 + .../src/bootstrap-code/post-request.js | 16 + .../src/cage-modules/pw.ts | 76 ++++ .../src/node/test-runner/legacy.ts | 12 +- .../hoppscotch-js-sandbox/src/shared-utils.ts | 382 +++++++----------- .../hoppscotch-js-sandbox/src/types/index.ts | 4 + .../src/relay/impl/desktop/v/1.ts | 37 +- .../src/relay/impl/web/v/1.ts | 74 +--- packages/hoppscotch-kernel/src/relay/v/1.ts | 14 + packages/hoppscotch-relay/src/interop.rs | 3 + packages/hoppscotch-relay/src/relay.rs | 53 ++- .../src-tauri/Cargo.toml | 4 + .../src-tauri/tauri.conf.json | 3 +- .../components/settings/NativeInterceptor.vue | 16 + .../src/platform/interceptors/native/index.ts | 211 +++++++--- 63 files changed, 833 insertions(+), 551 deletions(-) diff --git a/packages/hoppscotch-cli/package.json b/packages/hoppscotch-cli/package.json index 9e308f231d1..6cc16921bb2 100644 --- a/packages/hoppscotch-cli/package.json +++ b/packages/hoppscotch-cli/package.json @@ -1,6 +1,6 @@ { - "name": "@hoppscotch/cli", - "version": "0.24.0", + "name": "@devenap/hoppscotch-cli", + "version": "1.2.3", "description": "A CLI to run Hoppscotch test scripts in CI environments.", "homepage": "https://hoppscotch.io", "type": "module", diff --git a/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/digest-auth-success-coll.json b/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/digest-auth-success-coll.json index 16f0b6fca4c..0ae506443b4 100644 --- a/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/digest-auth-success-coll.json +++ b/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/digest-auth-success-coll.json @@ -29,7 +29,7 @@ "params": [], "headers": [], "endpoint": "<>", - "testScript": "pw.test(\"Status code is 200\", ()=> { pw.expect(pw.response.status).toBe(200);}); \n pw.test(\"Receives the www-authenticate header\", ()=> { pw.expect(pw.response.headers['www-authenticate']).toBeType('string');});", + "testScript": "pw.test(\"Status code is 200\", ()=> { pw.expect(pw.response.status).toBe(200);});", "preRequestScript": "", "responses": {}, "requestVariables": [] diff --git a/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/sample-coll.json b/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/sample-coll.json index b0ca8cecf2f..facdb85c474 100644 --- a/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/sample-coll.json +++ b/packages/hoppscotch-cli/src/__tests__/e2e/fixtures/collections/sample-coll.json @@ -15,7 +15,7 @@ "authActive": true }, "preRequestScript": "", - "testScript": "// Check status code is 200\npw.test(\"Status code is 200\", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\n// Check JSON response property\npw.test(\"Check JSON response property\", ()=> {\n pw.expect(pw.response.body.method).toBe(\"GET\");\n pw.expect(pw.response.body.headers).toBeType(\"object\");\n});", + "testScript": "// Check status code is 200\npw.test(\"Status code is 200\", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\n// Check JSON response property\npw.test(\"Check JSON response property\", ()=> {\n pw.expect(pw.response.body.method).toBe(\"GET\");\n pw.expect(pw.response.body.headers).toBeType(\"object\");\n }); \n\n// Check Content-Type\n pw.test(\"Check Content-Type\", () => {\n let contentType = null;\n for (const header of pw.response.headers) {\n if (header.key.toLowerCase() === 'content-type') {\n contentType = header.value;\n break;\n }\n}\npw.expect(contentType).toBe('application/json');\n });", "body": { "contentType": null, "body": null @@ -23,4 +23,4 @@ "requestVariables": [] } ] -} \ No newline at end of file +} diff --git a/packages/hoppscotch-cli/src/utils/collections.ts b/packages/hoppscotch-cli/src/utils/collections.ts index fa635783886..860b5c45b4f 100644 --- a/packages/hoppscotch-cli/src/utils/collections.ts +++ b/packages/hoppscotch-cli/src/utils/collections.ts @@ -34,6 +34,8 @@ import { processRequest, } from "./request"; import { getTestMetrics } from "./test"; +import {ProxyAgent} from "proxy-agent"; +import axios from "axios"; const { WARN, FAIL, INFO } = exceptionColors; @@ -132,8 +134,15 @@ const processCollection = async ( // Request processing initiated message. log(WARN(`\nRunning: ${chalk.bold(requestPath)}`)); + const agent = new ProxyAgent(); + const axiosInstance = axios.create({ + httpsAgent : agent, + httpAgent : agent, + proxy: false, // Disable axios's default proxy handling + }); + // Processing current request. - const result = await processRequest(processRequestParams)(); + const result = await processRequest(processRequestParams,axiosInstance)(); // Updating global & selected envs with new envs from processed-request output. const { global, selected } = result.envs; diff --git a/packages/hoppscotch-cli/src/utils/mutators.ts b/packages/hoppscotch-cli/src/utils/mutators.ts index 153e66b24a9..3fe2ba3eaf7 100644 --- a/packages/hoppscotch-cli/src/utils/mutators.ts +++ b/packages/hoppscotch-cli/src/utils/mutators.ts @@ -8,6 +8,8 @@ import { error } from "../types/errors"; import { FormDataEntry } from "../types/request"; import { isHoppErrnoException } from "./checks"; import { getResourceContents } from "./getters"; +import FormData from "form-data"; +import fsSync from "fs"; const getValidRequests = ( collections: HoppCollection[], @@ -52,20 +54,9 @@ const getValidRequests = ( export const toFormData = (values: FormDataEntry[]) => { const formData = new FormData(); - values.forEach(({ key, value, contentType }) => { - if (contentType) { - formData.append( - key, - new Blob([value], { - type: contentType, - }), - key - ); - - return; - } - - formData.append(key, value); + values.forEach(({ key, value }) => { + const isFilePath = typeof value === "string" && value.startsWith("/"); + formData.append(key, isFilePath ? fsSync.createReadStream(value) : value); }); return formData; diff --git a/packages/hoppscotch-cli/src/utils/pre-request.ts b/packages/hoppscotch-cli/src/utils/pre-request.ts index 4837ff6fd63..a12a944d867 100644 --- a/packages/hoppscotch-cli/src/utils/pre-request.ts +++ b/packages/hoppscotch-cli/src/utils/pre-request.ts @@ -33,6 +33,7 @@ import { fetchInitialDigestAuthInfo, generateDigestAuthHeader, } from "./auth/digest"; +import FormData from "form-data"; import { calculateHawkHeader } from "@hoppscotch/data"; @@ -388,7 +389,14 @@ export async function getEffectiveRESTRequest( const effectiveFinalBody = _effectiveFinalBody.right; - if ( + if (effectiveFinalBody instanceof FormData) { + effectiveFinalHeaders.push({ + active: true, + key: "Content-Type", + value: `multipart/form-data; boundary=${effectiveFinalBody.getBoundary()}`, + description: "", + }); + } else if ( request.body.contentType && !effectiveFinalHeaders.some( ({ key }) => key.toLowerCase() === "content-type" diff --git a/packages/hoppscotch-cli/src/utils/request.ts b/packages/hoppscotch-cli/src/utils/request.ts index 4f1611f2103..485a336090c 100644 --- a/packages/hoppscotch-cli/src/utils/request.ts +++ b/packages/hoppscotch-cli/src/utils/request.ts @@ -4,7 +4,7 @@ import { HoppRESTRequest, RESTReqSchemaVersion, } from "@hoppscotch/data"; -import axios, { Method } from "axios"; +import axios, { AxiosInstance,Method } from "axios"; import * as A from "fp-ts/Array"; import * as E from "fp-ts/Either"; import * as T from "fp-ts/Task"; @@ -102,7 +102,7 @@ export const createRequest = (req: EffectiveHoppRESTRequest): RequestConfig => { */ export const requestRunner = ( - requestConfig: RequestConfig + requestConfig: RequestConfig, axiosInstance: AxiosInstance ): TE.TaskEither => async () => { const start = hrtime(); @@ -112,7 +112,7 @@ export const requestRunner = requestConfig.url = new URL(requestConfig.url ?? "").toString(); let status: number; - const baseResponse = await axios(requestConfig); + const baseResponse = await axiosInstance(requestConfig); const { config } = baseResponse; // PR-COMMENT: type error const runnerResponse: RequestRunnerResponse = { @@ -199,7 +199,7 @@ const getRequest = { */ export const processRequest = ( - params: ProcessRequestParams + params: ProcessRequestParams, axiosInstance : AxiosInstance ): T.Task<{ envs: HoppEnvs; report: RequestReport }> => async () => { const { envs, path, request, delay, legacySandbox, collectionVariables } = @@ -271,7 +271,7 @@ export const processRequest = // Executing request-runner. const requestRunnerRes = await delayPromiseFunction< E.Either - >(requestRunner(requestConfig), delay); + >(requestRunner(requestConfig ,axiosInstance), delay); if (E.isLeft(requestRunnerRes)) { // Updating report for errors & current result report.errors.push(requestRunnerRes.left); diff --git a/packages/hoppscotch-common/locales/en.json b/packages/hoppscotch-common/locales/en.json index 7c4c60cfc53..871c8dcf0c3 100644 --- a/packages/hoppscotch-common/locales/en.json +++ b/packages/hoppscotch-common/locales/en.json @@ -991,6 +991,7 @@ "extensions": "Browser extension", "extensions_use_toggle": "Use the browser extension to send requests (if present)", "follow": "Follow us", + "follow_redirects": "Automatically follow redirects", "general": "General", "general_description": " General settings used in the application", "interceptor": "Interceptor", diff --git a/packages/hoppscotch-common/src/components/app/Footer.vue b/packages/hoppscotch-common/src/components/app/Footer.vue index 6676e5d8a4e..6732f65cc6c 100644 --- a/packages/hoppscotch-common/src/components/app/Footer.vue +++ b/packages/hoppscotch-common/src/components/app/Footer.vue @@ -11,7 +11,7 @@ @click="EXPAND_NAVIGATION = !EXPAND_NAVIGATION" /> -