Setting user agents in browser environments

Overview

When using Speakeasy SDKs in browser environments, setting the user agent header directly is restricted by browser security policies. This guide demonstrates how to use SDK hooks to set user agent information in a browser-compatible way.

Understanding the challenge

Browsers prevent direct modification of the User-Agent header for security reasons. When attempting to set this header in browser environments:

  • The header modification may silently fail
  • No error will be thrown
  • The original browser user agent will be used instead

Solution using SDK hooks

We can use a BeforeRequestHook to implement a fallback mechanism that ensures our SDK version information is properly transmitted, even in browser environments.

import { BeforeRequestContext, BeforeRequestHook, Awaitable } from "./types";
import { SDK_METADATA } from "../lib/config";
export class CustomUserAgentHook implements BeforeRequestHook {
beforeRequest(_: BeforeRequestContext, request: Request): Awaitable<Request> {
const version = SDK_METADATA.sdkVersion;
const ua = `speakeasy-sdk/${version}`;
// Try to set the standard user-agent header first
request.headers.set("user-agent", ua);
// Check if the header was actually set (it may silently fail in browsers)
if (!request.headers.get("user-agent")) {
// Fall back to a custom header if the user-agent couldn't be set
request.headers.set("x-sdk-user-agent", ua);
}
return request;
}
}

How the hook works

  1. The hook attempts to set the standard user-agent header first
  2. It then checks if the header was successfully set
  3. If the header wasn’t set (which happens in browsers), it falls back to using a custom header x-sdk-user-agent
  4. This ensures your SDK version information is always transmitted, regardless of browser restrictions

Adding the hook to your SDK

Register the hook in your SDK’s hook registration file:

import { CustomUserAgentHook } from "./user_agent";
import { Hooks } from "./types";
export function initHooks(hooks: Hooks) {
hooks.registerBeforeRequestHook(new CustomUserAgentHook());
}

Using hooks with generated SDKs

When working with SDKs generated by Speakeasy, you’ll want to follow these best practices:

  • Always implement the fallback mechanism to handle browser environments
  • Use a consistent format for your user agent string (e.g., sdk-name/version)
  • Consider including additional relevant information in the user agent string
  • Test the implementation in both browser and non-browser environments

This approach ensures your Speakeasy SDK can properly identify itself to your API while remaining compatible with browser security restrictions.