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;
	}
Exemple #3
0
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);
}
Exemple #4
0
// 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;
}
Exemple #5
0
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;
}