XX-net/XX-Net · error

forward_local fail, command

Error message

forward_local fail, command:%s, path:%s, headers: %s, payload: %s

What it means

forward_local attempted the local direct HTTP request via simple_http_client.request() and got a falsy response (None/empty), meaning the local connection to the target failed entirely. The command, path, headers and payload are logged for diagnosis before returning.

Solutions

  1. Check basic local connectivity to the host (curl --resolve / ping the resolved IP)
  2. Verify DNS resolution is correct; switch to a trusted DNS resolver to rule out pollution
  3. Let the proxy fall back to the GAE/AGENT path for blocked sites instead of DIRECT
  4. If it affects all sites, fix the local network/firewall before debugging the proxy
Defensive patterns

Strategy: fallback

Validate before calling

import socket
try:
    socket.create_connection((host, 80), timeout=3).close()
    direct_ok = True
except OSError:
    direct_ok = False

Try / catch

response = simple_http_client.request(...)
if not response:
    xlog.warn('forward_local fail ...')
    self.go_AGENT()  # retry via GAE instead of failing the client

Prevention

When it happens

Trigger: simple_http_client.request() returns None because the TCP connection to the origin failed, the connection was reset, or the response could not be parsed — e.g. target site unreachable, local network down, DNS failure, or firewall reset.

Common situations: Target site blocked or unreachable from the local network; local internet outage; DNS pollution resolving the host to a bogus IP; the site resetting non-proxy connections. Compare with the GAE path: if DIRECT fails but GAE works, it's network blocking.

Related errors


AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27). Data as JSON: /api/errors/28db80be11f4b3c4. Report an issue: GitHub.

Appendix: source

Thrown at code/default/gae_proxy/local/proxy_handler.py:109

    def forward_local(self):
        """
        If browser send localhost:xxx request to GAE_proxy,
        we forward it to localhost.
        """
        request_headers = dict((k.title(), v) for k, v in list(self.headers.items()))
        payload = b''
        if b'Content-Length' in request_headers:
            try:
                payload_len = int(request_headers.get(b'Content-Length', 0))
                payload = self.rfile.read(payload_len)
            except Exception as e:
                xlog.warn('forward_local read payload failed:%s', e)
                return

        response = simple_http_client.request(self.command, self.path, request_headers, payload)
        if not response:
            xlog.warn("forward_local fail, command:%s, path:%s, headers: %s, payload: %s",
                self.command, self.path, request_headers, payload)
            return

        out_list = []
        out_list.append(b"HTTP/1.1 %d\r\n" % response.status)
        for key in response.headers:
            key = key.title()
            out_list.append(b"%s: %s\r\n" % (key, response.headers[key]))
        out_list.append(b"\r\n")
        out_list.append(response.text)

        self.wfile.write(b"".join(out_list))

    def send_method_allows(self, headers, payload):
        xlog.debug("send method allow list for:%s %s", self.command, self.path)
        # Refer: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

        response = \

View on GitHub (pinned to cfa5bc17b6)