void WorkMonitor::vpackHandler(VPackBuilder* b, WorkDescription* desc) { HttpHandler* handler = desc->_data.handler; const HttpRequest* request = handler->getRequest(); b->add("type", VPackValue("http-handler")); b->add("protocol", VPackValue(request->protocol())); b->add("method", VPackValue(HttpRequest::translateMethod(request->requestType()))); b->add("url", VPackValue(request->fullUrl())); b->add("httpVersion", VPackValue((int) request->protocolVersion())); b->add("database", VPackValue(request->databaseName())); b->add("user", VPackValue(request->user())); b->add("taskId", VPackValue(request->clientTaskId())); if (handler->_statistics != nullptr) { b->add("startTime", VPackValue(handler->_statistics->_requestStart)); } auto& info = request->connectionInfo(); b->add("server", VPackValue(VPackValueType::Object)); b->add("address", VPackValue(info.serverAddress)); b->add("port", VPackValue(info.serverPort)); b->close(); b->add("client", VPackValue(VPackValueType::Object)); b->add("address", VPackValue(info.clientAddress)); b->add("port", VPackValue(info.clientPort)); b->close(); b->add("endpoint", VPackValue(VPackValueType::Object)); b->add("address", VPackValue(info.endpoint)); b->add("type", VPackValue(info.portType())); b->close(); }
foreach (QObject* object, children()) { HttpHandler* handler = qobject_cast<HttpHandler*>(object); if (handler && handler->handleRequest(connection)) return true; }
int uwsgiProcessor::process(wsgi_request *wsgi_req) { if (uwsgi_parse_vars(wsgi_req)) { return -1; } Request req(wsgi_req); Response res(wsgi_req); HttpHandler* proc = processor(); return proc->request_handler(req,res); }
// AddAsk 支持两种参数列表 // 1. AddAsk(http, ask, callback) // 支持回调,等待回调继续处理 // 2. AddAsk(http, ask) // 没有回调,处理完就ok了 static int tolua_luaexport_AddAsk00(lua_State* tolua_S) { tolua_Error tolua_err; if (!tolua_isusertype(tolua_S,1,"HttpHandler",0,&tolua_err)) { tolua_error(tolua_S,"#ferror in function 'JsonDecode'.",&tolua_err); return 0; } else { HttpHandler* http = (HttpHandler*)tolua_tousertype(tolua_S,1,0); LuaAsk* ask = NULL; if (tolua_isusertype(tolua_S,2,"DBAsk",0,&tolua_err)) { ask = (DBAsk*)tolua_tousertype(tolua_S,2,0); } else if (tolua_isusertype(tolua_S,2,"HttpAsk",0,&tolua_err)) { ask = (HttpAsk*)tolua_tousertype(tolua_S,2,0); } else if (tolua_isusertype(tolua_S,2,"ServerAsk",0,&tolua_err)) { ask = (ServerAsk*)tolua_tousertype(tolua_S,2,0); } else { ask = (LuaAsk*)tolua_tousertype(tolua_S,2,0); } int nFuncId = 0; if (lua_isfunction(tolua_S, 3)) {// 2. AddAsk(http, ask) // 没有回调,处理完就ok了 lua_pushvalue(tolua_S, 3); nFuncId = luaL_ref(tolua_S, LUA_REGISTRYINDEX); } if (!http->addAsk(ask, nFuncId)) { return 0; } } return 1; }
Handler::status_e RestBatchHandler::execute() { // extract the request type const HttpRequest::HttpRequestType type = _request->requestType(); if (type != HttpRequest::HTTP_REQUEST_POST && type != HttpRequest::HTTP_REQUEST_PUT) { generateError(HttpResponse::METHOD_NOT_ALLOWED, TRI_ERROR_HTTP_METHOD_NOT_ALLOWED); return Handler::HANDLER_DONE; } string boundary; if (! getBoundary(&boundary)) { // invalid content-type or boundary sent generateError(HttpResponse::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid content-type or boundary received"); return Handler::HANDLER_FAILED; } size_t errors = 0; // get authorization header. we will inject this into the subparts string authorization = _request->header("authorization"); // create the response _response = createResponse(HttpResponse::OK); _response->setContentType(_request->header("content-type")); // setup some auxiliary structures to parse the multipart message MultipartMessage message(boundary.c_str(), boundary.size(), _request->body(), _request->body() + _request->bodySize()); SearchHelper helper; helper.message = &message; helper.searchStart = (char*) message.messageStart; // iterate over all parts of the multipart message while (true) { // get the next part from the multipart message if (! extractPart(&helper)) { // error generateError(HttpResponse::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid multipart message received"); LOGGER_WARNING << "received a corrupted multipart message"; return Handler::HANDLER_FAILED; } // split part into header & body const char* partStart = helper.foundStart; const char* partEnd = partStart + helper.foundLength; const size_t partLength = helper.foundLength; const char* headerStart = partStart; char* bodyStart = NULL; size_t headerLength = 0; size_t bodyLength = 0; // assume Windows linebreak \r\n\r\n as delimiter char* p = strstr((char*) headerStart, "\r\n\r\n"); if (p != NULL) { headerLength = p - partStart; bodyStart = p + 4; bodyLength = partEnd - bodyStart; } else { // test Unix linebreak p = strstr((char*) headerStart, "\n\n"); if (p != NULL) { headerLength = p - partStart; bodyStart = p + 2; bodyLength = partEnd - bodyStart; } else { // no delimiter found, assume we have only a header headerLength = partLength; } } // set up request object for the part LOGGER_TRACE << "part header is " << string(headerStart, headerLength); HttpRequest* request = new HttpRequest(headerStart, headerLength); if (bodyLength > 0) { LOGGER_TRACE << "part body is " << string(bodyStart, bodyLength); request->setBody(bodyStart, bodyLength); } if (authorization.size()) { // inject Authorization header of multipart message into part message request->setHeader("authorization", 13, authorization.c_str()); } HttpHandler* handler = _server->createHandler(request); if (! handler) { delete request; generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, "could not create handler for batch part processing"); return Handler::HANDLER_FAILED; } Handler::status_e status = Handler::HANDLER_FAILED; do { try { status = handler->execute(); } catch (triagens::basics::TriagensError const& ex) { handler->handleError(ex); } catch (std::exception const& ex) { triagens::basics::InternalError err(ex, __FILE__, __LINE__); handler->handleError(err); } catch (...) { triagens::basics::InternalError err("executeDirectHandler", __FILE__, __LINE__); handler->handleError(err); } } while (status == Handler::HANDLER_REQUEUE); if (status == Handler::HANDLER_FAILED) { // one of the handlers failed, we must exit now delete handler; generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, "executing a handler for batch part failed"); return Handler::HANDLER_FAILED; } HttpResponse* partResponse = handler->getResponse(); if (partResponse == 0) { delete handler; generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, "could not create a response for batch part request"); return Handler::HANDLER_FAILED; } const HttpResponse::HttpResponseCode code = partResponse->responseCode(); if (code >= 400) { // error ++errors; } // append the boundary for this subpart _response->body().appendText(boundary + "\r\nContent-Type: "); _response->body().appendText(_partContentType); if (helper.contentId != 0) { // append content-id _response->body().appendText("\r\nContent-Id: " + string(helper.contentId, helper.contentIdLength)); } _response->body().appendText("\r\n\r\n", 4); // remove some headers we don't need partResponse->setHeader("connection", 10, ""); partResponse->setHeader("server", 6, ""); // append the part response header partResponse->writeHeader(&_response->body()); // append the part response body _response->body().appendText(partResponse->body()); _response->body().appendText("\r\n", 2); delete handler; if (! helper.containsMore) { // we've read the last part break; } } // next part // append final boundary + "--" _response->body().appendText(boundary + "--"); if (errors > 0) { _response->setHeader(HttpResponse::getBatchErrorHeader(), StringUtils::itoa(errors)); } // success return Handler::HANDLER_DONE; }
HttpHandler* HttpHandlerFactory::createHandler(HttpRequest* request) { std::string const& path = request->requestPath(); // In the bootstrap phase, we would like that coordinators answer the // following to endpoints, but not yet others: if (MaintenanceMode) { if ((!ServerState::instance()->isCoordinator() && path.find("/_api/agency/agency-callbacks") == std::string::npos) || (path != "/_api/shard-comm" && path.find("/_api/agency/agency-callbacks") == std::string::npos && path.find("/_api/aql") == std::string::npos)) { LOG(DEBUG) << "Maintenance mode: refused path: " << path; return new MaintenanceHandler(request); } } std::unordered_map<std::string, create_fptr> const& ii = _constructors; std::string const* modifiedPath = &path; std::string prefix; auto i = ii.find(path); // no direct match, check prefix matches if (i == ii.end()) { LOG(TRACE) << "no direct handler found, trying prefixes"; // find longest match size_t const pathLength = path.size(); for (auto const& p : _prefixes) { size_t const pSize = p.size(); if (path.compare(0, pSize, p) == 0) { if (pSize < pathLength && path[pSize] == '/') { if (prefix.size() < pSize) { prefix = p; } } } } if (prefix.empty()) { LOG(TRACE) << "no prefix handler found, trying catch all"; i = ii.find("/"); if (i != ii.end()) { LOG(TRACE) << "found catch all handler '/'"; size_t l = 1; size_t n = path.find_first_of('/', l); while (n != std::string::npos) { request->addSuffix(path.substr(l, n - l)); l = n + 1; n = path.find_first_of('/', l); } if (l < path.size()) { request->addSuffix(path.substr(l)); } modifiedPath = &ROOT_PATH; request->setPrefix(ROOT_PATH); } } else { LOG(TRACE) << "found prefix match '" << prefix << "'"; size_t l = prefix.size() + 1; size_t n = path.find_first_of('/', l); while (n != std::string::npos) { request->addSuffix(path.substr(l, n - l)); l = n + 1; n = path.find_first_of('/', l); } if (l < path.size()) { request->addSuffix(path.substr(l)); } modifiedPath = &prefix; i = ii.find(prefix); request->setPrefix(prefix); } } // no match void* data = nullptr; if (i == ii.end()) { if (_notFound != nullptr) { HttpHandler* notFoundHandler = _notFound(request, data); notFoundHandler->setServer(this); return notFoundHandler; } LOG(TRACE) << "no not-found handler, giving up"; return nullptr; } // look up data { auto const& it = _datas.find(*modifiedPath); if (it != _datas.end()) { data = (*it).second; } } LOG(TRACE) << "found handler for path '" << *modifiedPath << "'"; HttpHandler* handler = i->second(request, data); handler->setServer(this); return handler; }
ConnectionHandler* HttpServer::createConnectionHandler(qintptr socketDescriptor) const { HttpHandler* http = new HttpHandler(callback); http->setSocketCreator(new TcpSocketCreation(socketDescriptor)); return http; }
HttpHandler* HttpHandlerFactory::createHandler (HttpRequest* request) { #if 0 READ_LOCKER(_maintenanceLock); if (_maintenance) { return ((S*) this)->createMaintenanceHandler(); } #endif map<string, create_fptr> const& ii = _constructors; string path = request->requestPath(); map<string, create_fptr>::const_iterator i = ii.find(path); void* data = 0; // no direct match, check prefix matches if (i == ii.end()) { LOG_TRACE("no direct handler found, trying prefixes"); // find longest match string prefix; vector<string> const& jj = _prefixes; const size_t pathLength = path.size(); for (vector<string>::const_iterator j = jj.begin(); j != jj.end(); ++j) { string const& p = *j; const size_t pSize = p.size(); if (path.compare(0, pSize, p) == 0) { if (pSize < pathLength && path[pSize] == '/') { if (prefix.size() < pSize) { prefix = p; } } } } if (prefix.empty()) { LOG_TRACE("no prefix handler found, trying catch all"); i = ii.find("/"); if (i != ii.end()) { LOG_TRACE("found catch all handler '/'"); size_t l = 1; size_t n = path.find_first_of('/', l); while (n != string::npos) { request->addSuffix(path.substr(l, n - l).c_str()); l = n + 1; n = path.find_first_of('/', l); } if (l < path.size()) { request->addSuffix(path.substr(l).c_str()); } path = "/"; request->setPrefix(path.c_str()); } } else { LOG_TRACE("found prefix match '%s'", prefix.c_str()); size_t l = prefix.size() + 1; size_t n = path.find_first_of('/', l); while (n != string::npos) { request->addSuffix(path.substr(l, n - l).c_str()); l = n + 1; n = path.find_first_of('/', l); } if (l < path.size()) { request->addSuffix(path.substr(l).c_str()); } path = prefix; request->setPrefix(path.c_str()); i = ii.find(path); } } // no match if (i == ii.end()) { if (_notFound != 0) { HttpHandler* notFoundHandler = _notFound(request, data); notFoundHandler->setServer(this); return notFoundHandler; } else { LOG_TRACE("no not-found handler, giving up"); return 0; } } // look up data map<string, void*> const& jj = _datas; map<string, void*>::const_iterator j = jj.find(path); if (j != jj.end()) { data = j->second; } LOG_TRACE("found handler for path '%s'", path.c_str()); HttpHandler* handler = i->second(request, data); handler->setServer(this); return handler; }
HttpHandler::status_t RestBatchHandler::execute () { // extract the request type const HttpRequest::HttpRequestType type = _request->requestType(); if (type != HttpRequest::HTTP_REQUEST_POST && type != HttpRequest::HTTP_REQUEST_PUT) { generateError(HttpResponse::METHOD_NOT_ALLOWED, TRI_ERROR_HTTP_METHOD_NOT_ALLOWED); return status_t(HttpHandler::HANDLER_DONE); } string boundary; // invalid content-type or boundary sent if (! getBoundary(&boundary)) { generateError(HttpResponse::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid content-type or boundary received"); return status_t(HttpHandler::HANDLER_FAILED); } LOG_TRACE("boundary of multipart-message is '%s'", boundary.c_str()); size_t errors = 0; // get authorization header. we will inject this into the subparts string authorization = _request->header("authorization"); // create the response _response = createResponse(HttpResponse::OK); _response->setContentType(_request->header("content-type")); // setup some auxiliary structures to parse the multipart message MultipartMessage message(boundary.c_str(), boundary.size(), _request->body(), _request->body() + _request->bodySize()); SearchHelper helper; helper.message = &message; helper.searchStart = (char*) message.messageStart; // iterate over all parts of the multipart message while (true) { // get the next part from the multipart message if (! extractPart(&helper)) { // error generateError(HttpResponse::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "invalid multipart message received"); LOG_WARNING("received a corrupted multipart message"); return status_t(HttpHandler::HANDLER_FAILED); } // split part into header & body const char* partStart = helper.foundStart; const char* partEnd = partStart + helper.foundLength; const size_t partLength = helper.foundLength; const char* headerStart = partStart; char* bodyStart = nullptr; size_t headerLength = 0; size_t bodyLength = 0; // assume Windows linebreak \r\n\r\n as delimiter char* p = strstr((char*) headerStart, "\r\n\r\n"); if (p != nullptr && p + 4 <= partEnd) { headerLength = p - partStart; bodyStart = p + 4; bodyLength = partEnd - bodyStart; } else { // test Unix linebreak p = strstr((char*) headerStart, "\n\n"); if (p != nullptr && p + 2 <= partEnd) { headerLength = p - partStart; bodyStart = p + 2; bodyLength = partEnd - bodyStart; } else { // no delimiter found, assume we have only a header headerLength = partLength; } } // set up request object for the part LOG_TRACE("part header is: %s", string(headerStart, headerLength).c_str()); HttpRequest* request = new HttpRequest(_request->connectionInfo(), headerStart, headerLength, _request->compatibility(), false); if (request == nullptr) { generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY); return status_t(HttpHandler::HANDLER_FAILED); } // we do not have a client task id here request->setClientTaskId(0); // inject the request context from the framing (batch) request // the "false" means the context is not responsible for resource handling request->setRequestContext(_request->getRequestContext(), false); request->setDatabaseName(_request->databaseName()); if (bodyLength > 0) { LOG_TRACE("part body is '%s'", string(bodyStart, bodyLength).c_str()); request->setBody(bodyStart, bodyLength); } if (authorization.size()) { // inject Authorization header of multipart message into part message request->setHeader("authorization", 13, authorization.c_str()); } HttpHandler* handler = _server->createHandler(request); if (! handler) { delete request; generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, "could not create handler for batch part processing"); return status_t(HttpHandler::HANDLER_FAILED); } HttpHandler::status_t status(HttpHandler::HANDLER_FAILED); do { handler->prepareExecute(); try { status = handler->execute(); } catch (triagens::basics::Exception const& ex) { handler->handleError(ex); } catch (std::exception const& ex) { triagens::basics::Exception err(TRI_ERROR_INTERNAL, ex.what(), __FILE__, __LINE__); handler->handleError(err); } catch (...) { triagens::basics::Exception err(TRI_ERROR_INTERNAL, __FILE__, __LINE__); handler->handleError(err); } handler->finalizeExecute(); } while (status.status == HttpHandler::HANDLER_REQUEUE); if (status.status == HttpHandler::HANDLER_FAILED) { // one of the handlers failed, we must exit now delete handler; generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, "executing a handler for batch part failed"); return status_t(HttpHandler::HANDLER_FAILED); } HttpResponse* partResponse = handler->getResponse(); if (partResponse == nullptr) { delete handler; generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, "could not create a response for batch part request"); return status_t(HttpHandler::HANDLER_FAILED); } const HttpResponse::HttpResponseCode code = partResponse->responseCode(); if (code >= 400) { // error ++errors; } // append the boundary for this subpart _response->body().appendText(boundary + "\r\nContent-Type: "); _response->body().appendText(triagens::rest::HttpRequest::BatchContentType); if (helper.contentId != 0) { // append content-id _response->body().appendText("\r\nContent-Id: " + string(helper.contentId, helper.contentIdLength)); } _response->body().appendText(TRI_CHAR_LENGTH_PAIR("\r\n\r\n")); // remove some headers we don't need partResponse->setHeader(TRI_CHAR_LENGTH_PAIR("connection"), ""); partResponse->setHeader(TRI_CHAR_LENGTH_PAIR("server"), ""); // append the part response header partResponse->writeHeader(&_response->body()); // append the part response body _response->body().appendText(partResponse->body()); _response->body().appendText(TRI_CHAR_LENGTH_PAIR("\r\n")); delete handler; if (! helper.containsMore) { // we've read the last part break; } } // next part // append final boundary + "--" _response->body().appendText(boundary + "--"); if (errors > 0) { _response->setHeader(HttpResponse::BatchErrorHeader, StringUtils::itoa(errors)); } // success return status_t(HttpHandler::HANDLER_DONE); }
HttpHandler* HttpHandlerFactory::createHandler (HttpRequest* request) { if (MaintenanceMode) { return new MaintenanceHandler(request); } unordered_map<string, create_fptr> const& ii = _constructors; string path = request->requestPath(); auto i = ii.find(path); void* data = nullptr; // no direct match, check prefix matches if (i == ii.end()) { LOG_TRACE("no direct handler found, trying prefixes"); // find longest match string prefix; size_t const pathLength = path.size(); for (auto const& p : _prefixes) { const size_t pSize = p.size(); if (path.compare(0, pSize, p) == 0) { if (pSize < pathLength && path[pSize] == '/') { if (prefix.size() < pSize) { prefix = p; } } } } if (prefix.empty()) { LOG_TRACE("no prefix handler found, trying catch all"); i = ii.find("/"); if (i != ii.end()) { LOG_TRACE("found catch all handler '/'"); size_t l = 1; size_t n = path.find_first_of('/', l); while (n != string::npos) { request->addSuffix(path.substr(l, n - l)); l = n + 1; n = path.find_first_of('/', l); } if (l < path.size()) { request->addSuffix(path.substr(l)); } path = "/"; request->setPrefix(path.c_str()); } } else { LOG_TRACE("found prefix match '%s'", prefix.c_str()); size_t l = prefix.size() + 1; size_t n = path.find_first_of('/', l); while (n != string::npos) { request->addSuffix(path.substr(l, n - l)); l = n + 1; n = path.find_first_of('/', l); } if (l < path.size()) { request->addSuffix(path.substr(l)); } path = prefix; request->setPrefix(path.c_str()); i = ii.find(path); } } // no match if (i == ii.end()) { if (_notFound != nullptr) { HttpHandler* notFoundHandler = _notFound(request, data); notFoundHandler->setServer(this); return notFoundHandler; } else { LOG_TRACE("no not-found handler, giving up"); return nullptr; } } // look up data { auto const& it = _datas.find(path); if (it != _datas.end()) { data = (*it).second; } } LOG_TRACE("found handler for path '%s'", path.c_str()); HttpHandler* handler = i->second(request, data); handler->setServer(this); return handler; }