TestCafe Hammerhead Proxy
testcafe-hammerhead is a robust, low-level web proxy library serving as the core engine for the TestCafe end-to-end testing framework. It functions as a URL-rewriting proxy, transparently modifying URLs within proxied web pages and intercepting access to URL-containing properties to provide original values, making it appear to the client that the page is hosted at its original location. The current stable version is 31.7.7, with frequent patch and minor releases to address bugs, security vulnerabilities, and improve compatibility. Key differentiators include its ability to handle HTTP/HTTPS, WebSockets, EventSource, and file uploads, along with extensive request and response modification capabilities. It is primarily used programmatically to establish and configure proxy servers for web traffic manipulation.
Common errors
-
Failed to load resource: the server responded with a status of 500 (Internal Server Error) TypeError: ExprGen[itemType] is not a function
cause Hammerhead's processing of certain JavaScript files or malformed HTML can lead to internal server errors during resource loading.fixInspect the problematic JavaScript file or HTML for non-standard syntax or malformations. This issue was noted as possibly fixed in native automation versions. -
TypeError: Invalid URL error in prepareBaseUrl
cause An incorrectly formatted or unresolvable URL was passed to a Hammerhead component responsible for base URL preparation.fixEnsure all URLs provided to the proxy or within proxied content are valid and correctly encoded. Verify network connectivity for external resources. This was a fix in TestCafe v3.7.4 (which bumps Hammerhead). -
Sockets hanging (closes #7097) / socket hang up
cause Under specific network conditions or due to internal proxy handling, socket connections could become unresponsive or terminate unexpectedly.fixThis issue was specifically addressed and fixed in Hammerhead v31.6.4. Upgrade to v31.6.4 or a later version to resolve this. -
Fix: issue with module workers / worker postmessage targetUrl fixed
cause Problems with Hammerhead's handling of web module workers and their `postMessage` target URLs, leading to communication failures.fixThese issues were fixed in Hammerhead v31.7.7. Ensure you are using the latest version to avoid disruptions related to web workers.
Warnings
- breaking The `request` dependency was removed in v31.7.3. If your custom code or plugins implicitly relied on this package being available through TestCafe Hammerhead's internal mechanisms, you might need to update your implementations to use standard Node.js `http`/`https` modules or an alternative HTTP client.
- gotcha Hammerhead's URL rewriting and script injection can interfere with source maps, making debugging challenging. Application runtime exceptions reported by tools like Sentry may have broken stack frames due to the modifications.
- gotcha Proxied pages may exhibit 'incorrect behavior' if the URL rewriting or script injection process encounters issues, particularly with complex or non-standard HTML/JavaScript. This can lead to unexpected test failures or application malfunctions.
- gotcha Google reCAPTCHA v3 often fails when pages are served via the Hammerhead proxy, consistently returning a low score (e.g., 0.1). This can block logins or other functionalities on sites demanding a higher reCAPTCHA score.
- breaking As of TestCafe v3.0.0, which heavily relies on Hammerhead, native CDP automation became the default for Chromium-based browsers, and support for Internet Explorer was removed. While Hammerhead itself supports non-CDP browsers, TestCafe's default behavior may impact test environments.
- breaking The minimum required Node.js version is `>=14.0.0`. Running with older Node.js versions will result in compatibility issues and potential failures.
Install
-
npm install testcafe-hammerhead -
yarn add testcafe-hammerhead -
pnpm add testcafe-hammerhead
Imports
- createProxy
const createProxy = require('testcafe-hammerhead').createProxy;import { createProxy } from 'testcafe-hammerhead'; - Proxy
import { Proxy } from 'testcafe-hammerhead'; - ProxyOptions
import { ProxyOptions } from 'testcafe-hammerhead';
Quickstart
import { createProxy } from 'testcafe-hammerhead';
import * as http from 'http';
// Configure the Hammerhead proxy instance
const proxy = createProxy({
port: 8000,
hostname: 'localhost',
// Optionally, you can specify an external proxy to chain to
// externalProxyHost: process.env.EXTERNAL_PROXY_HOST ?? '',
// externalProxyPort: parseInt(process.env.EXTERNAL_PROXY_PORT ?? '8080', 10),
});
// Create a standard Node.js HTTP server
const server = http.createServer((req, res) => {
// Pass incoming requests to the Hammerhead proxy's request handler
proxy.onRequest(req, res);
});
// Listen on the configured port
server.listen(proxy.port, () => {
console.log(`Hammerhead proxy listening on http://${proxy.hostname}:${proxy.port}`);
console.log(`Try visiting a URL like: http://${proxy.hostname}:${proxy.port}/http://example.com`);
});
// You can register custom event handlers with the proxy instance
proxy.on('request', (req, res, next) => {
// console.log(`Proxying request for: ${req.url}`);
next(); // Must call next() to continue processing the request
});
proxy.on('error', (error) => {
console.error('Hammerhead proxy error:', error);
});
// Graceful shutdown
process.on('SIGINT', () => {
console.log('Shutting down Hammerhead proxy...');
server.close(() => {
console.log('HTTP server closed.');
proxy.close(() => {
console.log('Hammerhead proxy instance closed.');
process.exit(0);
});
});
});