From 49f301a65c3f09652dbbcdab2a7d3a0956450047 Mon Sep 17 00:00:00 2001 From: jackkav Date: Mon, 1 Jun 2026 04:34:54 +0200 Subject: [PATCH] adapt req hooks --- packages/insomnia/src/common/har.ts | 33 +--------- .../src/network/network-adapter.node.ts | 19 +++++- .../src/network/network-adapter.renderer.ts | 34 +++++++--- packages/insomnia/src/network/network.ts | 62 +++++-------------- 4 files changed, 59 insertions(+), 89 deletions(-) diff --git a/packages/insomnia/src/common/har.ts b/packages/insomnia/src/common/har.ts index f18893c37b..56998a6c2a 100644 --- a/packages/insomnia/src/common/har.ts +++ b/packages/insomnia/src/common/har.ts @@ -1,14 +1,10 @@ -import clone from 'clone'; import type * as Har from 'har-format'; import { Cookie as ToughCookie } from 'tough-cookie'; import type { BaseModel, Environment, Request, RequestGroup, Response, Workspace } from '~/insomnia-data'; import { models, services } from '~/insomnia-data'; +import { applyRequestHooks } from '~/network/network-adapter'; -import * as plugins from '../plugins'; -import * as pluginApp from '../plugins/context/app'; -import * as pluginRequest from '../plugins/context/request'; -import * as pluginStore from '../plugins/context/store'; import { RenderError } from '../templating/render-error'; import type { RenderedRequest } from '../templating/types'; import { parseGraphQLReqeustBody } from '../utils/graph-ql'; @@ -248,7 +244,7 @@ export async function exportHarRequest(requestId: string, environmentOrWorkspace export async function exportHarWithRequest(request: Request, environmentId?: string, addContentLength = false) { try { const renderResult = await getRenderedRequestAndContext({ request, environment: environmentId }); - const renderedRequest = await _applyRequestPluginHooks(renderResult.request, renderResult.context); + const renderedRequest = await applyRequestHooks(renderResult.request, renderResult.context); parseGraphQLReqeustBody(renderedRequest); return exportHarWithRenderedRequest(renderedRequest, addContentLength); } catch (err) { @@ -260,31 +256,6 @@ export async function exportHarWithRequest(request: Request, environmentId?: str } } -async function _applyRequestPluginHooks( - renderedRequest: RenderedRequest, - renderedContext: Record, -): Promise { - let newRenderedRequest = renderedRequest; - - for (const { plugin, hook } of await plugins.getRequestHooks()) { - newRenderedRequest = clone(newRenderedRequest); - const context = { - ...(pluginApp.init() as Record), - ...(pluginRequest.init(newRenderedRequest, renderedContext) as Record), - ...(pluginStore.init(plugin) as Record), - }; - - try { - await hook(context); - } catch (err) { - err.plugin = plugin; - throw err; - } - } - - return newRenderedRequest; -} - export async function exportHarWithRenderedRequest(renderedRequest: RenderedRequest, addContentLength = false) { const url = smartEncodeUrl(renderedRequest.url, renderedRequest.settingEncodeUrl); diff --git a/packages/insomnia/src/network/network-adapter.node.ts b/packages/insomnia/src/network/network-adapter.node.ts index 746e2c2216..6ea4b11ccb 100644 --- a/packages/insomnia/src/network/network-adapter.node.ts +++ b/packages/insomnia/src/network/network-adapter.node.ts @@ -39,8 +39,7 @@ export const appendTimelineLines = (timelinePath: string, logs: string[]): Promi export const getAuthHeader = (r: RenderedRequest, u: string): Promise => getAuthHeaderFromMain(r, u); -export const executeCurlRequest = (options: CurlRequestOptions): Promise => - curlRequest(options); +export const executeCurlRequest = (options: CurlRequestOptions): Promise => curlRequest(options); export const runScript = (options: { script: string; @@ -51,6 +50,22 @@ export async function applyRequestHooks( newRenderedRequest: RenderedRequest, renderedContext: Record, ): Promise { + const { request: reqCtx } = pluginRequest.init(newRenderedRequest, renderedContext); + const defaultHeaders = reqCtx.getEnvironmentVariable('DEFAULT_HEADERS'); + if (defaultHeaders && typeof defaultHeaders === 'object' && !Array.isArray(defaultHeaders)) { + for (const name of Object.keys(defaultHeaders)) { + const value = (defaultHeaders as Record)[name]; + if (reqCtx.hasHeader(name)) { + console.log(`[header] Skip setting default header ${name}. Already set to ${value}`); + } else if (value === 'null') { + reqCtx.removeHeader(name); + console.log(`[header] Remove default header ${name}`); + } else { + reqCtx.setHeader(name, value); + console.log(`[header] Set default header ${name}: ${value}`); + } + } + } const pluginIndex = require('../plugins/index'); for (const { plugin, hook } of await pluginIndex.getRequestHooks()) { const context = { diff --git a/packages/insomnia/src/network/network-adapter.renderer.ts b/packages/insomnia/src/network/network-adapter.renderer.ts index c03f93780b..cc2ca8bf07 100644 --- a/packages/insomnia/src/network/network-adapter.renderer.ts +++ b/packages/insomnia/src/network/network-adapter.renderer.ts @@ -1,3 +1,6 @@ +import clone from 'clone'; + +import { filterHeaders } from '~/common/misc'; import type { RequestHeader } from '~/insomnia-data'; import { plugins as pluginsBridge } from '~/plugins/renderer-bridge'; import type { RenderedRequest } from '~/templating/types'; @@ -7,8 +10,7 @@ import type { CurlRequestOptions, ResponsePatch } from '../main/network/libcurl- import { cancellableCurlRequest } from './cancellation'; import { runScriptConcurrently } from './concurrency'; -export const getTimelinePath = (responseId: string): Promise => - window.main.timeline.getPath(responseId); +export const getTimelinePath = (responseId: string): Promise => window.main.timeline.getPath(responseId); export const appendToTimelineOnError = (timelinePath: string, data: string): Promise => window.main.timeline.appendToFile({ timelinePath, data }); @@ -19,8 +21,7 @@ export const appendTimelineLines = (timelinePath: string, logs: string[]): Promi export const getAuthHeader = (r: RenderedRequest, u: string): Promise => window.main.getAuthHeader(r, u); -export const executeCurlRequest = (options: CurlRequestOptions) => - cancellableCurlRequest(options); +export const executeCurlRequest = (options: CurlRequestOptions) => cancellableCurlRequest(options); export const runScript = (options: { script: string; @@ -31,11 +32,28 @@ export async function applyRequestHooks( newRenderedRequest: RenderedRequest, renderedContext: Record, ): Promise { - if (!await pluginsBridge.hasRequestHooks()) { - return newRenderedRequest; + const request = clone(newRenderedRequest); + const defaultHeaders = renderedContext['DEFAULT_HEADERS']; + if (defaultHeaders && typeof defaultHeaders === 'object' && !Array.isArray(defaultHeaders)) { + for (const name of Object.keys(defaultHeaders)) { + const value = (defaultHeaders as Record)[name]; + const existing = filterHeaders(request.headers, name); + if (existing.length) { + console.log(`[header] Skip setting default header ${name}. Already set to ${value}`); + } else if (value === 'null') { + request.headers = request.headers.filter(h => filterHeaders([h], name).length === 0); + console.log(`[header] Remove default header ${name}`); + } else { + request.headers.push({ name, value: String(value) }); + console.log(`[header] Set default header ${name}: ${value}`); + } + } + } + if (!(await pluginsBridge.hasRequestHooks())) { + return request; } return pluginsBridge.applyRequestHooks({ - renderedRequest: newRenderedRequest, + renderedRequest: request, projectId: renderedContext.getProjectId(), environment: renderedContext, }); @@ -46,7 +64,7 @@ export async function applyResponseHooks( renderedRequest: RenderedRequest, renderedContext: Record, ): Promise { - if (!await pluginsBridge.hasResponseHooks()) { + if (!(await pluginsBridge.hasResponseHooks())) { return response; } return pluginsBridge.applyResponseHooks({ diff --git a/packages/insomnia/src/network/network.ts b/packages/insomnia/src/network/network.ts index 6e50e55025..a0fb28efbd 100644 --- a/packages/insomnia/src/network/network.ts +++ b/packages/insomnia/src/network/network.ts @@ -1,4 +1,3 @@ -import clone from 'clone'; import orderedJSON from 'json-order'; import type { @@ -45,7 +44,6 @@ import { generateId, getContentTypeHeader, getLocationHeader, getSetCookieHeader import { getRenderedRequestAndContext } from '../common/render'; import { ascendingFirstIndexStringSort } from '../common/sorting'; import type { HeaderResult, ResponsePatch } from '../main/network/libcurl-promise'; -import * as pluginRequest from '../plugins/context/request'; import { RenderError } from '../templating/render-error'; import type { RenderedRequest, RenderPurpose } from '../templating/types'; import { maskOrDecryptVaultDataIfNecessary } from '../templating/utils'; @@ -799,7 +797,7 @@ export const tryToTransformRequestWithPlugins = async (renderResult: { }) => { const { request, context } = renderResult; try { - return await _applyRequestPluginHooks(request, context); + return await applyRequestHooks(request, context); } catch { throw new Error(`Failed to transform request with plugins: ${request._id}`); } @@ -951,7 +949,19 @@ export const responseTransform = async ( return response; } console.log(`[network] Response succeeded req=${patch.parentId} status=${response.statusCode || '?'}`); - return await _applyResponsePluginHooks(response, renderedRequest, context); + try { + return await applyResponseHooks(response, renderedRequest, context); + } catch (err) { + console.log('[plugin] Response hook failed', err, response); + return { + url: renderedRequest.url, + error: `[plugin] Response hook failed err=${err instanceof Error ? err.message : String(err)}`, + elapsedTime: 0, + statusMessage: 'Error', + settingSendCookies: renderedRequest.settingSendCookies, + settingStoreCookies: renderedRequest.settingStoreCookies, + }; + } }; export function getAuthQueryParams(authentication: RequestAuthentication) { if (authentication.disabled) { @@ -1041,50 +1051,6 @@ export const getCurrentUrl = ({ headerResults, finalUrl }: { headerResults: any; } }; -export async function _applyRequestPluginHooks(renderedRequest: RenderedRequest, renderedContext: Record) { - const newRenderedRequest = clone(renderedRequest); - - // Apply built-in default-headers hook in the renderer (no IPC needed) - const { request: reqCtx } = pluginRequest.init(newRenderedRequest, renderedContext); - const defaultHeaders = reqCtx.getEnvironmentVariable('DEFAULT_HEADERS'); - if (defaultHeaders && typeof defaultHeaders === 'object' && !Array.isArray(defaultHeaders)) { - for (const name of Object.keys(defaultHeaders)) { - const value = (defaultHeaders as Record)[name]; - if (reqCtx.hasHeader(name)) { - console.log(`[header] Skip setting default header ${name}. Already set to ${value}`); - } else if (value === 'null') { - reqCtx.removeHeader(name); - console.log(`[header] Remove default header ${name}`); - } else { - reqCtx.setHeader(name, value); - console.log(`[header] Set default header ${name}: ${value}`); - } - } - } - - return applyRequestHooks(newRenderedRequest, renderedContext); -} - -export async function _applyResponsePluginHooks( - response: ResponsePatch, - renderedRequest: RenderedRequest, - renderedContext: Record, -): Promise { - try { - return await applyResponseHooks(response, renderedRequest, renderedContext); - } catch (err) { - console.log('[plugin] Response hook failed', err, response); - return { - url: renderedRequest.url, - error: `[plugin] Response hook failed err=${err instanceof Error ? err.message : String(err)}`, - elapsedTime: 0, // 0 because this path is hit during plugin calls - statusMessage: 'Error', - settingSendCookies: renderedRequest.settingSendCookies, - settingStoreCookies: renderedRequest.settingStoreCookies, - }; - } -} - export const defaultSendActionRuntime: SendActionRuntime = { appendTimeline: appendTimelineLines, };