Skip to content

HTTP

HTTP lifecycle events are available in both the renderer and main entries. Requires the http permission. Registration disposables are tracked automatically.

Renderer

Use hc.http.onAfterSend when you only need to react to completed sends in the UI — no main entry or polling required. Prefer this over a main entry + custom IPC + polling for history or recent-requests panels.

Main entry

Optional main entry modules export activate(hc) and deactivate() like renderer entries, but run inside the SES-hardened utilityProcess. Use this entry for HTTP hooks and custom IPC — not for React UI.

Import MainPluginContext from @harborclient/sdk (or @harborclient/sdk/main for main-only plugins) and type your entry as activate(hc: MainPluginContext).

HTTP lifecycle hooks (onBeforeSend, onAfterSend, onBeforeScripts, onAfterScripts) are typically registered from the main entry. See Architecture.

hc.http.onAfterScripts(handler)

Available since v2.0.0

Signature:(handler: (context) => void | Promise<void>) => Disposable

Register a callback that runs after each request stage's scripts complete. Fires twice per send — once after pre-request scripts and once after post-request scripts. Requires the scripts:inject permission.

The context includes the final data bag for the stage, named hc.test results, console lines, and script error messages. Use this to collect injected test results or correlate values scripts wrote into hc.data.

typescript
import type { MainPluginContext } from '@harborclient/sdk';

export function activate(hc: MainPluginContext): void {
  hc.http.onAfterScripts(async (ctx) => {
    if (ctx.phase !== 'post') {
      return;
    }
    const failed = ctx.tests.filter((test) => !test.passed);
    if (failed.length) {
      await hc.storage.set('lastFailures', failed);
    }
  });
}

hc.http.onAfterSend(handler)

Available since v2.0.0

Signature:(handler: (request, response) => void | Promise<void>) => Disposable

Register a callback that runs after the response is received. Requires the http permission.

For UI-only plugins that react to completed sends (history, recent-requests, response diff), prefer renderer-side hc.http.onAfterSend in the renderer entry — it fires in-process with no main entry, custom IPC channel, or polling. Use this main-process hook when you need to run logic in the SES-hardened utilityProcess or mutate shared main-side state.

typescript
hc.http.onAfterSend(async (request, response) => {
  console.log(request.method, request.url, response.status);
});

hc.http.onBeforeScripts(handler)

Available since v2.0.0

Signature:(handler: (context) => void | Promise<void>) => Disposable

Register a callback that runs before each request stage's scripts. Fires twice per send — once with phase: 'pre' and once with phase: 'post'. Requires the scripts:inject permission.

Injected scripts run as a synthetic scope ahead of collection/folder/request scripts. Within each stage (before-all, before-each, main, after-each, after-all), plugin scripts run before host scripts in that stage. Use context.scripts.data to seed the shared hc.data bag visible to every script in the send.

See Baseline tests, Trace correlation, and Production guard for complete walkthroughs.

typescript
import type { MainPluginContext } from '@harborclient/sdk';

export function activate(hc: MainPluginContext): void {
  hc.http.onBeforeScripts((ctx) => {
    if (ctx.phase !== 'pre') {
      return;
    }
    ctx.scripts.data.traceId = crypto.randomUUID();
    ctx.scripts.beforeAll.push({
      name: 'Stamp trace id',
      script: `hc.request.headers.set('X-Trace-Id', hc.data.traceId);`
    });
  });
}

hc.http.onBeforeSend(handler)

Available since v2.7.0

Signature:(handler: (request) => void | Promise<void>) => Disposable

Register a callback that runs before each outgoing HTTP request. Mutate the request object to change method, URL, headers, or body. Requires the http permission. Remove a header with delete request.headers['Header-Name'].

typescript
import type { MainPluginContext } from '@harborclient/sdk';

export function activate(hc: MainPluginContext): void {
  hc.http.onBeforeSend(async (request) => {
    request.headers['X-Plugin-Trace'] = '1';
    delete request.headers['Authorization'];
  });
}