Skip to content

Code Node: this.helpers.httpRequest Ignores Redirect Disabling Options (maxRedirects, followRedirect) When HTTP Proxy is Configured #15091

Description

@elementrcode

Bug Description

Just a heads up that I got AI to help me write this, as it had me going through a lot of testing and verifying to make sure the issue was consistent, but since it's a bit out of my depth, I might not be able to give more in depth answers than I've already provided here 🤷‍♂️

Environment:

  • n8n Version: 1.90.2
  • Database: PostgreSQL
  • n8n EXECUTIONS_PROCESS: main (Default)
  • Running n8n via: Docker (using docker.n8n.io/n8nio/n8n:latest, via Coolify)
  • Operating System: Ubuntu (Server OS)
  • Date Observed: May 5, 2025

Describe the bug

The this.helpers.httpRequest function in the Code node does not reliably honor options intended to disable HTTP redirect following (maxRedirects: 0 or followRedirect: false) when the request is configured to go through an HTTP proxy using the proxy option.

Even when maxRedirects: 0 is explicitly set, the underlying HTTP client (Axios + follow-redirects, based on stack traces) still follows redirects when a proxy is specified. This has been confirmed by observing the actual network traffic via the proxy server's logs (Tinyproxy with LOG_LEVEL: Connect).

This bug manifests in different ways depending on the target URL:

  1. Simple Redirects (e.g., httpbin.org/redirect/1): Network logs show the client makes the initial request, receives a redirect, and incorrectly makes a second request to the redirect target, despite maxRedirects: 0. The response object returned to the Code node environment can be inconsistent or incomplete.
  2. Redirect Loops (e.g., specific private APIs): If the target server's redirect behavior (when accessed via proxy) forms a loop, the helper function throws an ERR_FR_TOO_MANY_REDIRECTS error, even though maxRedirects: 0 should have prevented the very first redirect from being followed.

Crucially, performing the exact same requests using curl from the command line with the same proxy server and the --max-redirs 0 flag correctly stops at the first redirect (or receives the expected non-redirect response). This indicates the issue lies specifically within the n8n helper/Axios proxy+redirect handling logic, not the proxy server or target API itself.

To Reproduce

Steps To Reproduce

  1. Set up any standard HTTP proxy server (e.g., Tinyproxy using kalaksi/tinyproxy Docker image) accessible from your n8n instance. Ensure it allows CONNECT requests to httpbin.org. Assume the proxy is at http://YOUR_PROXY_IP:PORT. (Note: Tested successfully using proxy http://37.27.4.175:8888).

  2. Configure the proxy server to log connections verbosely (e.g., Tinyproxy LOG_LEVEL: Connect).

  3. Create a new n8n workflow with a Code node.

  4. Paste the following JavaScript code into the Code node:

    // --- Configuration ---
    const url = '[http://httpbin.org/redirect/1](http://httpbin.org/redirect/1)'; // Public URL that issues a 302 redirect
    const proxyUrl = 'http://YOUR_PROXY_IP:PORT'; // !! REPLACE WITH YOUR PROXY !!
    
    // --- Request Options ---
    const options = {
      method: 'GET',
      url: url,
      proxy: { // Structured proxy object
          protocol: 'http',
          host: proxyUrl.split(':')[1].substring(2),
          port: parseInt(proxyUrl.split(':')[2])
      },
      // --- Attempt to Disable Redirects ---
      maxRedirects: 0, // Standard Axios option to disable redirects
    
      // --- Allow non-2xx status codes ---
      validateStatus: function (status) {
        return status >= 100 && status < 600;
      },
      timeout: 30000
    };
    
    let resultData = {};
    console.log("Attempting request with redirect disabling via proxy:", JSON.stringify(options, null, 2));
    
    try {
      const response = await this.helpers.httpRequest(options);
      // This block might be reached incorrectly if redirect is followed
      console.log(`Request completed with status: ${response.status}`);
      resultData = {
        statusCode: response.status,
        headers: response.headers,
        body: response.data,
        // This flag will likely be TRUE if the bug occurs
        redirectFollowedIncorrectly: (response.status >= 200 && response.status < 300)
      };
       if (response.status === 302 && response.headers.location) {
         console.log(`SUCCESS (Expected Behavior): Received 302 redirecting to ${response.headers.location}`);
      } else if (response.status >= 200 && response.status < 300) {
         console.warn(`FAILURE (Bug Triggered): Received ${response.status} instead of 302. Redirects were likely followed.`);
      } else {
         console.log(`Received unexpected status code: ${response.status}`);
      }
    } catch (error) {
      // Handle potential errors (like ERR_FR_TOO_MANY_REDIRECTS in loop scenarios)
      console.error("Error during HTTP request:", error);
      resultData = { error: true, message: error.message, code: error.code };
      if (error.response) {
          resultData.response = { statusCode: error.response.status, headers: error.response.headers };
      }
    }
    return [{ json: resultData }];
  5. Update proxyUrl in the code with your actual proxy details.

  6. Simultaneously: Run the Code node and monitor the proxy server logs.

Expected behavior

Expected behavior

  • Code Node Output: Should return an object containing statusCode: 302, and the headers object should include a location key pointing to /get. redirectFollowedIncorrectly should be false.
  • Proxy Logs: Should show only one request being proxied: GET http://httpbin.org/redirect/1.

Actual behavior

  • Code Node Output: Often returns statusCode: 200 and redirectFollowedIncorrectly: true, indicating the redirect was followed despite maxRedirects: 0. In other scenarios involving redirect loops, it throws ERR_FR_TOO_MANY_REDIRECTS.
  • Proxy Logs: Clearly show two requests being proxied:
    1. GET http://httpbin.org/redirect/1
    2. GET http://httpbin.org/get (or the relevant redirect target)
      This confirms the client followed the redirect despite the maxRedirects: 0 option passed to the helper.

Workaround

Use the "Execute Command" node to run a curl command with the desired proxy settings and the --max-redirs 0 flag. Parse the stdout for the required response data. This requires curl to be available in the n8n execution environment and appropriate permissions.

Operating System

Ubuntu LTS

n8n Version

1.90.2

Node.js Version

lts

Database

PostgreSQL

Execution mode

main (default)

Metadata

Metadata

Assignees

No one assigned

    Labels

    StaleIssue was stale

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions