I'm putting together an API with warp, and I'm trying to make it so that certain data can be requested cross-origin via POST. However, as soon as I add .and(warp::body::json()) to the filter, CORS stops working. I am testing CORS by going to http://example.com and issuing fetch() calls with http://127.0.0.1:8081 as URL from JavaScript via Firefox' developer tools. It may be me doing something wrong here, but should that be the case I don't understand what it might be.
Code snippet where CORS does not work even though I imagine it should:
not-working.zip
Code snippet where CORS does work as I imagine it should:
working.zip
I can confirm this, having the same issue.
Oh you just need to tell cors to allow the content-type header, because we are using the json body, like this:
let cors = warp::cors()
.allow_methods(&[Method::POST])
.allow_header("content-type");
If you get this error in the browser console:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
That's just because the response data wasn't json, but the request did work.
Oh you just need to tell cors to allow the
content-typeheader, because we are using the json body, like this:let cors = warp::cors() .allow_methods(&[Method::POST]) .allow_header("content-type");
Could you apply this to the code in not-working.zip and re-send it? I tried doing it like you proposed here but the result stays the same.
This is the code I ran:
fetch("http://127.0.0.1:8081/apples", {method: "POST", body: JSON.stringify({num: 25})})
I ran it in the browser's development tools on http://example.com
Try adding this header to fetch:
fetch("http://127.0.0.1:8081/apples", {
method: "POST",
body: JSON.stringify({num: 25}),
headers: {"Content-type": "application/json; charset=UTF-8"}
})
Try adding this header to fetch:
fetch("http://127.0.0.1:8081/apples", { method: "POST", body: JSON.stringify({num: 25}), headers: {"Content-type": "application/json; charset=UTF-8"} })
That did the trick! Thank you. I'm thinking it might be worth noting something about CORS and headers in the documentation though as I (and seemingly 3 other people) also seem to have ran into this, but I'm not sure how this would be formulated. Not only that, but I would argue this is inconsistent with how the API works in general, as at least in some other cases it is only required that you to specify what's allowed as a way to disallow others (such as with allow_origin(), see https://github.com/seanmonstar/warp/issues/614).
Question is then whether to let that be a separate issue or convert this one.
Nice, that was a little tricky for me as well. I'm not sure about documentation either, maybe a adding a example to the repo would be enough.
I was running into this while trying to hit a warp endpoint defined like this:
let cors = warp::cors()
.allow_any_origin()
.allow_headers(vec!["content-type"])
.allow_methods(&[warp::http::Method::GET, warp::http::Method::POST]);
warp::path!("v1" / "redacted")
.and(warp::get())
.and(warp::body::json())
.and_then(handlers::get_redacted_v1_handler)
.with(warp::log("routes"))
.with(cors)
.recover(error::recover);
While using axios like this:
const URL = `${process.env.BACKEND_URL}/v1/redacted`;
return axios
.request({
method: "GET",
url: URL,
})
.then(response => {
console.log(`< ${response.status} GET ${URL}`);
});
Changing warp::get() to warp::post() and axios method: "GET" to "POST" had no change... but then changing the axios side to the following fixed my issue.
return axios
.request({
method: "POST",
url: URL,
data: {
'myjsonkey': "myjsonstring",
},
headers: {
"Content-type": "application/json; charset=UTF-8",
},
})
I'm not quite sure where the issue is as hitting my warp endpoint from Postman was working fine. But I very specifically had to do the above. Even omitting the data:{ } section of my axios request causes CORS issues, where instead I'd expect a 400 with: Request body deserialize error: EOF while parsing a value at line 1 column 0
Most helpful comment
Try adding this header to fetch: