[Python] Chrome sending wrong Origin header on 127.0.0.1

Discussão em 'Python' iniciado por Stack, Maio 16, 2025.

  1. Stack

    Stack Membro Participativo

    TL;DR:

    When a frontend web page is served from http://localhost:5173, sending a CORS request to http://127.0.0.1:8000 results in an incorrect Origin header being sent:

    • Expected Origin header: Origin: http://localhost:5173
    • Actual Origin header: Origin: http://127.0.0.1 (wrong host, and no port)

    This happens only when the backend request target is 127.0.0.1:8000. If the target is localhost:8000, the Origin header is correct.

    Is this a BUG of Google Chrome, or is there a justification for this behavior?

    Details:

    I am testing a web application written by myself. The frontend (localhost:5173) sends http request to the backend (http://localhost:8000) when clicking a button

    The Origin header seems to work differently. If I send an GET request to the backend with target host "http://localhost:8000", the preflight request will be sent with header "Origin: http://localhost:5173", which is expected.

    However, if I send the request with target host "http://127.0.0.1:8000", the preflight request will be sent with header "Origin: http://127.0.0.1", which is not the correct origin (The correct origin should be "http://localhost:5173").

    This caused CORS errors even when setting CORS plugins (preflight requests were sent using wrong Origin header, getting wrong Access-Control-Allow-Origin response headers, and furthermore triggered the CORS error).

    I am including a very simple example, which is a python file that starts 2 servers (on 5173 and 8000), with 2 buttons on the frontend page. You can click for them and observe its preflight requests, and you will see the incorrect Origin header.

    My question: Is this a BUG of Google Chrome, or is there a justification for this behavior?

    Environment settings:

    • MacBook Pro (Apple M3 Max);
    • MacOS Sequoia 15.4.1;
    • Chrome Version 136.0.7103.114 (Official) (arm64)

    Code to demostrate this:

    from fastapi import FastAPI, Request
    from fastapi.responses import HTMLResponse, JSONResponse
    from fastapi.middleware.cors import CORSMiddleware
    import uvicorn

    app = FastAPI()
    app.add_middleware(
    CORSMiddleware,
    allow_origins=[
    "*",
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
    )
    @app.get("/test")
    async def test():
    return JSONResponse(content={"message": "Success from backend"})


    frontend_app = FastAPI()
    @frontend_app.get("/", response_class=HTMLResponse)
    async def index(request: Request):
    html_content = """
    <!DOCTYPE html>
    <html>
    <head>
    <title>CORS Test</title>
    </head>
    <body>
    <h1>CORS Origin Test (127.0.0.1 vs localhost)</h1>
    <button onclick="request127()">Request 127.0.0.1:8000</button>
    <button onclick="requestLocalhost()">Request localhost:8000</button>
    <pre id="result"></pre>

    <script>
    async function request127() {
    try {
    const res = await fetch('http://127.0.0.1:8000/test', {
    method: 'GET',
    headers: { authorization: 'Bearer token' }
    });
    const data = await res.json();
    document.getElementById('result').innerText = '127.0.0.1 Result: ' + JSON.stringify(data);
    } catch (err) {
    console.error(err);
    document.getElementById('result').innerText = '127.0.0.1 Failed';
    }
    }

    async function requestLocalhost() {
    try {
    const res = await fetch('http://localhost:8000/test', {
    method: 'GET',
    headers: { authorization: 'Bearer token' }
    });
    const data = await res.json();
    document.getElementById('result').innerText = 'localhost Result: ' + JSON.stringify(data);
    } catch (err) {
    console.error(err);
    document.getElementById('result').innerText = 'localhost Failed';
    }
    }
    </script>
    </body>
    </html>
    """
    return HTMLResponse(content=html_content)


    def run_backend():
    uvicorn.run(app, host="127.0.0.1", port=8000)


    def run_frontend():
    uvicorn.run(frontend_app, host="127.0.0.1", port=5173)

    if __name__ == "__main__":
    import multiprocessing

    p1 = multiprocessing.Process(target=run_backend)
    p2 = multiprocessing.Process(target=run_frontend)

    p1.start()
    p2.start()

    p1.join()
    p2.join()


    To run this code:

    pip install fastapi uvicorn
    python test_server.py

    Continue reading...

Compartilhe esta Página