diff --git a/include/http_server.h b/include/http_server.h index 0298718e..f46b436c 100644 --- a/include/http_server.h +++ b/include/http_server.h @@ -22,6 +22,7 @@ class HttpServer; struct h2o_custom_req_handler_t { h2o_handler_t super; HttpServer* http_server; + std::string api_auth_key_sent; }; struct h2o_custom_generator_t { diff --git a/src/http_server.cpp b/src/http_server.cpp index 4c3419c3..bf97130b 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -376,14 +376,12 @@ int HttpServer::catch_all_handler(h2o_handler_t *_h2o_handler, h2o_req_t *req) { query_map.erase("cache_ttl"); // Extract auth key from header. If that does not exist, look for a GET parameter. - std::string api_auth_key_sent = ""; - ssize_t auth_header_cursor = h2o_find_header_by_str(&req->headers, http_req::AUTH_HEADER, strlen(http_req::AUTH_HEADER), -1); if(auth_header_cursor != -1) { h2o_iovec_t & slot = req->headers.entries[auth_header_cursor].value; - api_auth_key_sent = std::string(slot.base, slot.len); + h2o_handler->api_auth_key_sent = std::string(slot.base, slot.len); } else if(query_map.count(http_req::AUTH_HEADER) != 0) { - api_auth_key_sent = query_map[http_req::AUTH_HEADER]; + h2o_handler->api_auth_key_sent = query_map[http_req::AUTH_HEADER]; } route_path *rpath = nullptr; @@ -431,12 +429,16 @@ int HttpServer::catch_all_handler(h2o_handler_t *_h2o_handler, h2o_req_t *req) { const std::string & body = std::string(req->entity.base, req->entity.len); std::vector embedded_params_vec; - bool authenticated = h2o_handler->http_server->auth_handler(query_map, embedded_params_vec, body, *rpath, - api_auth_key_sent); - if(!authenticated) { - std::string message = std::string("{\"message\": \"Forbidden - a valid `") + http_req::AUTH_HEADER + - "` header must be sent.\"}"; - return send_response(req, 401, message); + if(root_resource != "multi_search") { + // multi_search needs to be handled later because the API key could be part of request body and + // the whole request body might not be available right now. + bool authenticated = h2o_handler->http_server->auth_handler(query_map, embedded_params_vec, body, *rpath, + h2o_handler->api_auth_key_sent); + if(!authenticated) { + std::string message = std::string("{\"message\": \"Forbidden - a valid `") + http_req::AUTH_HEADER + + "` header must be sent.\"}"; + return send_response(req, 401, message); + } } std::shared_ptr request = std::make_shared(req, rpath->http_method, path_without_query, @@ -616,12 +618,23 @@ int HttpServer::async_req_cb(void *ctx, h2o_iovec_t chunk, int is_end_stream) { return 0; } -int HttpServer::process_request(const std::shared_ptr& request, const std::shared_ptr& response, route_path *rpath, - const h2o_custom_req_handler_t *handler) { +int HttpServer::process_request(const std::shared_ptr& request, const std::shared_ptr& response, + route_path *rpath, const h2o_custom_req_handler_t *handler) { //LOG(INFO) << "process_request called"; - const std::string& root_resource = (rpath->path_parts.empty()) ? "" : rpath->path_parts[0]; + + if(root_resource == "multi_search") { + // We can authenticate only when the full request body is available + bool authenticated = handler->http_server->auth_handler(request->params, request->embedded_params_vec, + request->body, *rpath, handler->api_auth_key_sent); + if(!authenticated) { + std::string message = std::string("{\"message\": \"Forbidden - a valid `") + http_req::AUTH_HEADER + + "` header must be sent.\"}"; + return send_response(request->_req, 401, message); + } + } + bool is_write = is_write_request(root_resource, rpath->http_method); if(is_write) {