diff --git a/arangod/GeneralServer/HttpCommTask.cpp b/arangod/GeneralServer/HttpCommTask.cpp index 97934abbf0..2aaf065a2f 100644 --- a/arangod/GeneralServer/HttpCommTask.cpp +++ b/arangod/GeneralServer/HttpCommTask.cpp @@ -104,7 +104,7 @@ void HttpCommTask::handleSimpleError(rest::ResponseCode code, int errorNum, void HttpCommTask::addResponse(HttpResponse* response) { resetKeepAlive(); - + _requestPending = false; // CORS response handling @@ -113,15 +113,18 @@ void HttpCommTask::addResponse(HttpResponse* response) { // access-control-allow-origin header now LOG(TRACE) << "handling CORS response"; - response->setHeaderNC(StaticStrings::AccessControlExposeHeaders, - StaticStrings::ExposedCorsHeaders); - // send back original value of "Origin" header - response->setHeaderNC(StaticStrings::AccessControlAllowOrigin, _origin); + response->setHeaderNCIfNotSet(StaticStrings::AccessControlAllowOrigin, _origin); // send back "Access-Control-Allow-Credentials" header - response->setHeaderNC(StaticStrings::AccessControlAllowCredentials, - (_denyCredentials ? "false" : "true")); + response->setHeaderNCIfNotSet(StaticStrings::AccessControlAllowCredentials, + (_denyCredentials ? "false" : "true")); + + // use "IfNotSet" here because we should not override HTTP headers set + // by Foxx applications + response->setHeaderNCIfNotSet(StaticStrings::AccessControlExposeHeaders, + StaticStrings::ExposedCorsHeaders); + } // set "connection" header, keep-alive is the default @@ -650,7 +653,7 @@ bool HttpCommTask::checkContentLength(HttpRequest* request, void HttpCommTask::processCorsOptions(std::unique_ptr request) { HttpResponse response(rest::ResponseCode::OK); - response.setHeaderNC(StaticStrings::Allow, StaticStrings::CorsMethods); + response.setHeaderNCIfNotSet(StaticStrings::Allow, StaticStrings::CorsMethods); if (!_origin.empty()) { LOG(TRACE) << "got CORS preflight request"; @@ -659,26 +662,24 @@ void HttpCommTask::processCorsOptions(std::unique_ptr request) { // send back which HTTP methods are allowed for the resource // we'll allow all - response.setHeaderNC(StaticStrings::AccessControlAllowMethods, - StaticStrings::CorsMethods); + response.setHeaderNCIfNotSet(StaticStrings::AccessControlAllowMethods, + StaticStrings::CorsMethods); if (!allowHeaders.empty()) { // allow all extra headers the client requested // we don't verify them here. the worst that can happen is that the - // client - // sends some broken headers and then later cannot access the data on - // the - // server. that's a client problem. - response.setHeaderNC(StaticStrings::AccessControlAllowHeaders, - allowHeaders); + // client sends some broken headers and then later cannot access the data on + // the server. that's a client problem. + response.setHeaderNCIfNotSet(StaticStrings::AccessControlAllowHeaders, + allowHeaders); LOG(TRACE) << "client requested validation of the following headers: " << allowHeaders; } // set caching time (hard-coded value) - response.setHeaderNC(StaticStrings::AccessControlMaxAge, - StaticStrings::N1800); + response.setHeaderNCIfNotSet(StaticStrings::AccessControlMaxAge, + StaticStrings::N1800); } processResponse(&response); diff --git a/lib/Rest/GeneralResponse.h b/lib/Rest/GeneralResponse.h index b164a2083c..be2faf27e8 100644 --- a/lib/Rest/GeneralResponse.h +++ b/lib/Rest/GeneralResponse.h @@ -106,7 +106,7 @@ class GeneralResponse { std::unordered_map headers() const { return _headers; } - + // adds a header. the header field name will be lower-cased void setHeader(std::string const& key, std::string const& value) { _headers[basics::StringUtils::tolower(key)] = value; @@ -121,7 +121,16 @@ class GeneralResponse { void setHeaderNC(std::string const& key, std::string&& value) { _headers[key] = std::move(value); } - + + // adds a header if not set. the header field name must be lower-cased + void setHeaderNCIfNotSet(std::string const& key, std::string const& value) { + if (_headers.find(key) != _headers.end()) { + // already set + return; + } + _headers.emplace(key, value); + } + public: virtual uint64_t messageId() const { return 1; }