Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preflight request gets denied when settings should allow it #48

Open
zibbe77 opened this issue Feb 9, 2024 · 10 comments
Open

Preflight request gets denied when settings should allow it #48

zibbe77 opened this issue Feb 9, 2024 · 10 comments
Labels
pending Pending for issue reporter to verify the fix

Comments

@zibbe77
Copy link

zibbe77 commented Feb 9, 2024

The example code underneath should fetch cookies from my backend thats on a different origin than my front end. However i get a error "Access to fetch at 'http://localhost:1234/cookies' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response." However if i understand the doc correct elysia-cors should allow it by default.

This is a example i made to narrow down the problem
Frontend
Open with live server - VS code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="post">
        <input type="text" placeholder="username" name="username">
        <input type="text" placeholder="password" name="password">
        <button>submit</button>
    </form>
    <script>
        document.querySelector("form").addEventListener("submit", (e) => {
            e.preventDefault();
            console.log("submitting");
            document.cookie = `username=${document.querySelector("input[name='username']").value}`;
            document.cookie = `password=${document.querySelector("input[name='password']").value}`;

            fetch("http://localhost:1234/cookies", {
                method: "GET",
                mode: "cors",
                headers: {
                    'Content-Type': 'application/json'
                },
                credentials: "include"
            })
            .then((response) => {
                console.log(response);
            });
        })
    </script>
</body>
</html>

Backend

import Elysia from "elysia";
import cors from "@elysiajs/cors";

const app = new Elysia();

app.use(
    cors({
        origin: true,
        methods: "*",
        allowedHeaders: "*",
        exposedHeaders: "*",
        credentials: true,
        maxAge: 50000,
        preflight: true,
    })
);

app.get("/cookies", ({ cookie: { username, password, icecream } }) => {
    icecream.value = "chocolate";
    console.log(username + ":" + password);
    return "you got me!";
});

app.listen(1234);
console.log("Server up and running at http://localhost:1234");

In addition to whats is shown here i have tried

  • app.options("*", cors());
  • To use firefox (my default is chrome )
  • Fetching the local network address

Dependancies
─ @elysiajs/[email protected]
├── [email protected]
└── [email protected]

@pandrRe
Copy link

pandrRe commented Feb 9, 2024

This is happens to me as well. If I set credentials as omit in the request, it goes through but it doesn't set the cookie anyway so it's useless.

@gcraig-kaiza
Copy link

gcraig-kaiza commented Feb 11, 2024

I was experiencing the same issue... I really hate CORS!

After a bit of an investigation, I found the following on MDN (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers):

The value "*" only counts as a special wildcard value for requests without credentials (requests without HTTP cookies or HTTP authentication information). In requests with credentials, it is treated as the literal header name "*" without special semantics. Note that the Authorization header can't be wildcarded and always needs to be listed explicitly.

As a temporary workaround, I have added the following global hook to my app which seems have resolved the issue:

const app = new Elysia()
  .onAfterHandle(({ request, set }) => {
    // Only process CORS requests
    if (request.method !== "OPTIONS") return;

    const allowHeader = set.headers["Access-Control-Allow-Headers"];
    if (allowHeader === "*") {
      set.headers["Access-Control-Allow-Headers"] =
        request.headers.get("Access-Control-Request-Headers") ?? "";
    }
  })
  .use(cors())
...

@zibbe77
Copy link
Author

zibbe77 commented Feb 12, 2024

Nice it works. However it does not work with live servers extension ...
Do i need to do someting with this issue ?

@FrancoLab
Copy link

This worked for me. I love this framework but the documentation does not give you enough details to solve these issues. And correct me if I am wrong, but this should not be an issue, this feels like a work around.

@varna
Copy link

varna commented Mar 12, 2024

I just needed a fix for one route so I did this:

export default new Elysia()
  .options("/report", async ({ set, request }) => {
    set.headers["Access-Control-Allow-Headers"] =
      request.headers.get("Access-Control-Request-Headers") ?? ""
  })
  .post(...)

I would probably be better to just make a PR that copies logic from https://github.com/expressjs/cors/blob/master/lib/index.js

@SaltyAom
Copy link
Member

SaltyAom commented Jul 9, 2024

Fixed with 010f999, published on 1.0.4

@SaltyAom SaltyAom added the pending Pending for issue reporter to verify the fix label Jul 9, 2024
@underthestars-zhy
Copy link

still get has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

@Ankan002
Copy link

I am also facing the same issue

@Cyberlane
Copy link

I'm completely blocked by this - is anybody working on a solution?

@bogeychan
Copy link
Collaborator

bogeychan commented Sep 24, 2024

Fix

app.use(
  cors({
    origin: true,
    methods: "*",
-    allowedHeaders: "*",
+    allowedHeaders: ["content-type"],
    exposeHeaders: "*",
    credentials: true,
    maxAge: 50000,
    preflight: true,
  })
);

OR

app.use(
  cors({
    origin: true,
    methods: "*",
-    allowedHeaders: "*",
    exposeHeaders: "*",
    credentials: true,
    maxAge: 50000,
    preflight: true,
  })
);

Explanation

Getting this CORS error: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response. is not a bug with the plugin / elysia itself:

Setting Access-Control-Allow-Headers to * doesn't have any semantic meaning if requests contain credentials (i.e., when the Access-Control-Allow-Credentials header is set to true), read the docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending Pending for issue reporter to verify the fix
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants