{"record":{"id":"6265bb2ae6fd2cf4","repo":"gofiber/fiber","slug":"client-https-to-http-redirect-blocked","errorCode":null,"errorMessage":"client: HTTPS to HTTP redirect blocked","messagePattern":"client: HTTPS to HTTP redirect blocked","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/errors.go","lineNumber":18,"sourceCode":"package client\n\nimport (\n\t\"errors\"\n)\n\nvar (\n\terrResponseChanTypeAssertion = errors.New(\"failed to type-assert to *Response\")\n\terrChanErrorTypeAssertion    = errors.New(\"failed to type-assert to chan error\")\n\terrRequestTypeAssertion      = errors.New(\"failed to type-assert to *Request\")\n\terrFileTypeAssertion         = errors.New(\"failed to type-assert to *File\")\n\terrCookieJarTypeAssertion    = errors.New(\"failed to type-assert to *CookieJar\")\n\terrSyncPoolBuffer            = errors.New(\"failed to retrieve buffer from a sync.Pool\")\n\n\t// ErrRedirectDowngrade is returned when a redirect leads from an HTTPS origin\n\t// to plaintext HTTP, on every transport. Set MaxRedirects to 0 to take such a\n\t// hop yourself instead.\n\tErrRedirectDowngrade = errors.New(\"client: HTTPS to HTTP redirect blocked\")\n)\n","sourceCodeStart":1,"sourceCodeEnd":20,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/client/errors.go#L1-L20","documentation":"Returned by resolveRedirect (client/transport.go:532) when the redirect starts on an HTTPS origin (wasHTTPS) and the Location header points to a plaintext http:// URL. The client refuses the hop on every transport — silently following it would expose the (already-encrypted) request — cookies, headers, body — to a downgrade attack. The middleware/proxy package ships its own equivalent sentinel for the same rule.","triggerScenarios":"An HTTPS server returns 301/302/307/308 with a Location like http://example.com/next; a misconfigured reverse proxy that rewrites Location to http://; an upstream that drops the scheme; HSTS-incompatible redirect chains. Reproducible via the 'https downgrade' test case (client/transport_test.go:615).","commonSituations":"Load balancer terminating TLS but advertising http:// in Location; dev/staging servers without TLS redirecting to plain HTTP; misconfigured CDN; upstream returning absolute http:// URLs in redirects.","solutions":["Fix the upstream so Location preserves the https:// scheme (configure your proxy/CDN to emit https redirects).","If the downgrade is intentional and safe (e.g. internal network), set Client.MaxRedirects to 0 and follow the hop yourself with a fresh HTTPS-or-HTTP-aware call.","On the proxy side, the same logic applies — DoRedirects rejects the downgrade; fix the origin or handle the redirect manually.","Add an integration test asserting no Location header in your responses downgrades the scheme."],"exampleFix":"// before\nclient.SetMaxRedirects(5)\nresp, err := req.Send() // upstream 302 Location: http://... -> ErrRedirectDowngrade\n\n// after (opt out and follow yourself, only if safe)\nclient.SetMaxRedirects(0)\nresp, err := req.Send() // get the 302, then decide","handlingStrategy":"try-catch","validationCode":"// Pre-validate that the redirect target preserves the scheme\nfunc wouldDowngrade(base, location string) bool {\n    wasHTTPS := strings.EqualFold(urlScheme(base), \"https\")\n    u, err := url.Parse(location)\n    if err != nil || u.Scheme == \"\" { return false }\n    return wasHTTPS && strings.EqualFold(u.Scheme, \"http\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := req.Send()\nif errors.Is(err, fiber.ErrRedirectDowngrade) {\n    // surface to ops — the upstream is misconfigured; do NOT silently follow\n    // or set MaxRedirects(0) and handle the hop yourself only if it is safe\n}","preventionTips":["Ensure upstreams/CDNs preserve https in Location headers.","Treat ErrRedirectDowngrade as a security signal, not a transient error.","Add a redirect audit test that asserts no Location downgrades scheme."],"tags":["client","redirect","tls","security","http"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}