void StaticHandler::onRequest(std::unique_ptr<HTTPMessage> headers) noexcept { if (headers->getMethod() != HTTPMethod::GET) { ResponseBuilder(downstream_) .status(400, "Bad method") .body("Only GET is supported") .sendWithEOM(); return; } // a real webserver would validate this path didn't contain malicious // characters like '//' or '..' try { // + 1 to kill leading / file_ = std::make_unique<folly::File>(headers->getPath().c_str() + 1); } catch (const std::system_error& ex) { ResponseBuilder(downstream_) .status(404, "Not Found") .body(folly::to<std::string>("Could not find ", headers->getPath(), " ex=", folly::exceptionStr(ex))) .sendWithEOM(); return; } ResponseBuilder(downstream_) .status(200, "Ok") .send(); // use a CPU executor since read(2) of a file can block readFileScheduled_ = true; folly::getCPUExecutor()->add( std::bind(&StaticHandler::readFile, this, folly::EventBaseManager::get()->getEventBase())); }
void RequestHandlerAdaptor::onError(const HTTPException& error) noexcept { if (err_ != kErrorNone) { // we have already handled an error and upstream would have been deleted return; } if (error.getProxygenError() == kErrorTimeout) { setError(kErrorTimeout); if (responseStarted_) { sendAbort(); } else { ResponseBuilder(this) .status(408, "Request Timeout") .closeConnection() .sendWithEOM(); } } else if (error.getDirection() == HTTPException::Direction::INGRESS) { setError(kErrorRead); if (responseStarted_) { sendAbort(); } else { ResponseBuilder(this) .status(400, "Bad Request") .closeConnection() .sendWithEOM(); } } else { setError(kErrorWrite); } // Wait for detachTransaction to clean up }
void HelloV1::onEOM() noexcept { folly::fbstring out{}; auto task = executor()->addFuture([&out, input = parameter]() { // Sanitize input! // Process // Prepare output out = folly::sformat("{{\"response\":\"HelloV1 {}\"}}", input); }).onError([&out](const std::exception &e) { // DB error, or some such failure out = "{\"response\": \"server failed\"}"; LOG(ERROR) << e.what() << '\n'; }); task.wait(); ResponseBuilder(downstream_) .status(200, "OK") .header(HTTPHeaderCode::HTTP_HEADER_CONTENT_TYPE, JSON_content_type) .header(HTTPHeaderCode::HTTP_HEADER_CACHE_CONTROL, MAXAGE_4hour) .body(std::move(out)) .sendWithEOM(); }
void PushRequestHandler::onEOM() noexcept { ResponseBuilder(downstream_) .status(200, "OK") .header("Request-Number", folly::to<std::string>(stats_->getRequestCount())) .body(std::move(body_)) .sendWithEOM(); }
void Hola::onEOM() noexcept { ResponseBuilder(downstream_) .status(200, "OK") .header(HTTPHeaderCode::HTTP_HEADER_CONTENT_TYPE, JSON_content_type) .header(HTTPHeaderCode::HTTP_HEADER_CACHE_CONTROL, MAXAGE_4hour) .body("{\"response\": \"No habla espanol\"}") .sendWithEOM(); }
void StaticHandler::readFile(folly::EventBase* evb) { folly::IOBufQueue buf; while (file_ && !paused_) { // read 4k-ish chunks and foward each one to the client auto data = buf.preallocate(4000, 4000); auto rc = folly::readNoInt(file_->fd(), data.first, data.second); if (rc < 0) { // error VLOG(4) << "Read error=" << rc; file_.reset(); evb->runInEventBaseThread([this] { LOG(ERROR) << "Error reading file"; downstream_->sendAbort(); }); break; } else if (rc == 0) { // done file_.reset(); VLOG(4) << "Read EOF"; evb->runInEventBaseThread([this] { ResponseBuilder(downstream_) .sendWithEOM(); }); break; } else { buf.postallocate(rc); evb->runInEventBaseThread([this, body=buf.move()] () mutable { ResponseBuilder(downstream_) .body(std::move(body)) .send(); }); } } // Notify the request thread that we terminated the readFile loop evb->runInEventBaseThread([this] { readFileScheduled_ = false; if (!checkForCompletion() && !paused_) { VLOG(4) << "Resuming deferred readFile"; onEgressResumed(); } }); }
void HangmanHandler::onEOM() noexcept { folly::fbstring received_str; std::vector<folly::fbstring> wrong_guesses; folly::fbstring masked_sentence; folly::fbstring response_json; if(body_) { received_str = body_->moveToFbString(); std::cout << "Received string is " << received_str << std::endl; dynamic parsed = folly::parseJson(received_str); std::cout << "Request type is " << parsed["request_type"] << std::endl; /* * If the HTTP request is asking for guess */ if(parsed["request_type"] == "request_guess") { masked_sentence = parsed["masked_sentence"].getString(); for(size_t i = 0; i < parsed["wrong_guesses"].size(); i++) { wrong_guesses.push_back(parsed["wrong_guesses"][i].getString()); } folly::fbstring response_str = guesser_.guess(masked_sentence, wrong_guesses); std::cout << "Guesser returned a value: " << response_str << std::endl; folly::dynamic d = dynamic::object("guess_result", response_str); response_json = folly::toJson(d); } /* * If the HTTP request is asking for a new sentence, i.e. start a game */ else if(parsed["request_type"] == "request_sentence") { std::cout << "Received a new sentence request" << std::endl; folly::fbstring response_str = game_creator_.genSentence(); folly::dynamic d = dynamic::object("new_sentence", response_str); response_json = folly::toJson(d); } } std::cout << "JSON response is " << response_json << std::endl; ResponseBuilder(downstream_) .status(200, "OK") .header("Request-Number", folly::to<std::string>(stats_->getRequestCount())) .header("Access-Control-Allow-Origin", "*") //.body(std::move(body_)) .body(response_json) .sendWithEOM(); // For debug use std::cout << "Response Sent: " << response_json << std::endl; }
void PushRequestHandler::onRequest( std::unique_ptr<HTTPMessage> headers) noexcept { stats_->recordRequest(); if (!headers->getHeaders().getSingleOrEmpty("X-PushIt").empty()) { downstreamPush_ = downstream_->newPushedResponse(new PushHandler); if (!downstreamPush_) { // can't push return; } if(headers->getPath() == "/requestLargePush") { LOG(INFO) << "sending large push "; ResponseBuilder(downstreamPush_) .promise("/largePush", headers->getHeaders().getSingleOrEmpty(HTTP_HEADER_HOST)) .send(); ResponseBuilder(downstreamPush_) .status(200, "OK") .body(createLargeBody()) .sendWithEOM(); } else { LOG(INFO) << "sending small push "; ResponseBuilder(downstreamPush_) .promise("/pusheen", headers->getHeaders().getSingleOrEmpty(HTTP_HEADER_HOST)) .send(); ResponseBuilder(downstreamPush_) .status(200, "OK") .body(gPushBody) .sendWithEOM(); } } }
void RequestHandlerAdaptor::onHeadersComplete(std::unique_ptr<HTTPMessage> msg) noexcept { if (msg->getHeaders().exists(HTTP_HEADER_EXPECT)) { auto expectation = msg->getHeaders().getSingleOrEmpty(HTTP_HEADER_EXPECT); if (!boost::iequals(expectation, "100-continue")) { setError(kErrorUnsupportedExpectation); ResponseBuilder(this) .status(417, "Expectation Failed") .closeConnection() .sendWithEOM(); } else { ResponseBuilder(this) .status(100, "Continue") .send(); } } // Only in case of no error if (err_ == kErrorNone) { upstream_->onRequest(std::move(msg)); } }
void F2WebHandler::onEOM() noexcept { ResponseBuilder(downstream_) .status(200, "OK") .body(std::move(body_)) .sendWithEOM(); }