-
Notifications
You must be signed in to change notification settings - Fork 71
Description
Platform
ESP32
IDE / Tooling
pioarduino
What happened?
When testing, I often run my react app in dev mode on localhost.
The frontend app api points to my esp32 ip address in this case, which is in the local network.
The following ( recommended ) cors config in this case is the following
corsMiddleware.setHeaders("Origin, X-Requested-With, Content-Type, Accept, Authorization, SysAuthorization");
corsMiddleware.setMethods("GET,HEAD,OPTIONS,POST,PUT,DELETE");
corsMiddleware.setOrigin("*");When _credentials is true, the browser does not let "*" wildcard origin and it rejects the OPTIONS request. This is expected browser behaviour.
In order for this to work properly, we must set the origin to the request origin. This can not be done globally, but on individual requests.
I have cloned the AsyncCorsMiddleware and added a void checkAllowAnyOrigin(AsyncWebServerRequest *request, AsyncWebServerResponse *response); method. This method sets the Origin header to the request Origin, passes the browser check.
void ClonedCorsMiddleware::checkAllowAnyOrigin(AsyncWebServerRequest *request, AsyncWebServerResponse *response) {
if (allowAnyOrigin) {
std::string incomingOrigin = request->getHeader(asyncsrv::T_CORS_O)->value().c_str();
response->addHeader(asyncsrv::T_CORS_ACAO, incomingOrigin.c_str());
}
}
void ClonedCorsMiddleware::run(AsyncWebServerRequest *request, ArMiddlewareNext next) {
// Origin header ? => CORS handling
if (request->hasHeader(asyncsrv::T_CORS_O)) {
// check if this is a preflight request => handle it and return
if (request->method() == HTTP_OPTIONS) {
AsyncWebServerResponse *response = request->beginResponse(200);
addCORSHeaders(response);
checkAllowAnyOrigin(request, response);
request->send(response);
return;
}
// CORS request, no options => let the request pass and add CORS headers after
next();
AsyncWebServerResponse *response = request->getResponse();
if (response) {
addCORSHeaders(response);
checkAllowAnyOrigin(request, response);
}
} else {
// NO Origin header => no CORS handling
next();
}
}This is a hack right now because the _origin is set twice in the run method. I suggest a separate bool variable which can be toggled ( like allowAnyOrigin or allowCurrentOrigin ) which would allow the current Origin in the request.
Stack Trace
The code does not crash but browser does not care about the wildcard Origin header when credentials are true.
Minimal Reproductible Example (MRE)
Use the default CORS middleware with _credentials = true and try to reach the esp32 from an other ip address using origin as "*"
I confirm that:
- I have read the documentation.
- I have searched for similar discussions.
- I have searched for similar issues.
- I have looked at the examples.
- I have upgraded to the lasted version of ESPAsyncWebServer (and AsyncTCP for ESP32).