adapt req hooks

This commit is contained in:
jackkav
2026-06-01 04:34:54 +02:00
parent e333b748f7
commit 49f301a65c
4 changed files with 59 additions and 89 deletions

View File

@@ -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<string, any>,
): Promise<RenderedRequest> {
let newRenderedRequest = renderedRequest;
for (const { plugin, hook } of await plugins.getRequestHooks()) {
newRenderedRequest = clone(newRenderedRequest);
const context = {
...(pluginApp.init() as Record<string, any>),
...(pluginRequest.init(newRenderedRequest, renderedContext) as Record<string, any>),
...(pluginStore.init(plugin) as Record<string, any>),
};
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);

View File

@@ -39,8 +39,7 @@ export const appendTimelineLines = (timelinePath: string, logs: string[]): Promi
export const getAuthHeader = (r: RenderedRequest, u: string): Promise<RequestHeader | undefined> =>
getAuthHeaderFromMain(r, u);
export const executeCurlRequest = (options: CurlRequestOptions): Promise<CurlRequestOutput> =>
curlRequest(options);
export const executeCurlRequest = (options: CurlRequestOptions): Promise<CurlRequestOutput> => curlRequest(options);
export const runScript = (options: {
script: string;
@@ -51,6 +50,22 @@ export async function applyRequestHooks(
newRenderedRequest: RenderedRequest,
renderedContext: Record<string, any>,
): Promise<RenderedRequest> {
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<string, any>)[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 = {

View File

@@ -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<string> =>
window.main.timeline.getPath(responseId);
export const getTimelinePath = (responseId: string): Promise<string> => window.main.timeline.getPath(responseId);
export const appendToTimelineOnError = (timelinePath: string, data: string): Promise<void> =>
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<RequestHeader | undefined> =>
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<string, any>,
): Promise<RenderedRequest> {
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<string, any>)[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<string, any>,
): Promise<ResponsePatch> {
if (!await pluginsBridge.hasResponseHooks()) {
if (!(await pluginsBridge.hasResponseHooks())) {
return response;
}
return pluginsBridge.applyResponseHooks({

View File

@@ -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<string, any>) {
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<string, any>)[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<string, any>,
): Promise<ResponsePatch> {
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,
};