-
Notifications
You must be signed in to change notification settings - Fork 5
/
XkcdRequestHandler.cpp
108 lines (95 loc) · 3.25 KB
/
XkcdRequestHandler.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//
// Created by victor on 11/25/17.
//
#include <folly/executors/GlobalExecutor.h>
#include "XkcdRequestHandler.h"
#include "Validations.h"
#include <string>
using proxygen::HTTPMessage;
using proxygen::HTTPMethod;
using proxygen::ResponseBuilder;
using folly::HHWheelTimer;
namespace restdbxx {
void XkcdRequestHandler::onRequest(std::unique_ptr<proxygen::HTTPMessage> headers) noexcept {
if (headers->getMethod() != HTTPMethod::GET && headers->getMethod() != HTTPMethod::OPTIONS) {
ResponseBuilder(downstream_)
.status(401, "Method not allowed")
.sendWithEOM();
return;
}
folly::Optional<int> comic = folly::none;
if (headers->hasQueryParam("comic")) {
int comicNumber = headers->getIntQueryParam("comic", -1);
if (comicNumber != -1) comic = comicNumber;
}
folly::Promise<folly::dynamic> promise;
auto f = promise.getFuture();
folly::EventBaseManager::get()->getEventBase()
->runInLoop([comic, p = std::move(promise), this]() mutable {
auto req = new HTTPMessage();
std::stringstream ss;
ss << "https://xkcd.com/";
if (comic) {
ss << comic.value() << "/";
}
ss << "info.0.json";
req->setURL(ss.str());
req->setMethod(HTTPMethod::GET);
client->fetch(req, p);
});
f.then([this](folly::dynamic &comic) mutable {
VLOG(google::GLOG_INFO) << "Got a comic!";
ResponseBuilder(downstream_)
.status(200, "OK")
.header("RESTDBXX_QUERY_TIME", std::to_string(client->get_elapsed()))
.header(proxygen::HTTPHeaderCode::HTTP_HEADER_CONTENT_TYPE, "application/json")
.body(folly::toPrettyJson(comic))
.sendWithEOM();
return;
}).onError([this](const std::runtime_error &e) {
ResponseBuilder(downstream_)
.status(500, "unexpected error")
.body(e.what())
.sendWithEOM();
});
}
void XkcdRequestHandler::onBody(std::unique_ptr<folly::IOBuf> body) noexcept {
if (_body) {
_body->prependChain(std::move(body));
} else {
_body = std::move(body);
}
}
void XkcdRequestHandler::onUpgrade(proxygen::UpgradeProtocol prot) noexcept {
}
void XkcdRequestHandler::onEOM() noexcept {
}
void XkcdRequestHandler::requestComplete()noexcept {
delete this;
}
void XkcdRequestHandler::onError(proxygen::ProxygenError err) noexcept {
delete this;
}
XkcdRequestHandler::XkcdRequestHandler(const std::string &path, folly::HHWheelTimer *pTimer) :
_mount_path{path}, client{std::make_shared<JsonClient>(pTimer)} {
}
void XkcdRequestHandlerFactory::onServerStart(folly::EventBase *evb) noexcept {
timer->_timer = HHWheelTimer::newTimer(
evb,
std::chrono::milliseconds(HHWheelTimer::DEFAULT_TICK_INTERVAL),
folly::AsyncTimeout::InternalEnum::NORMAL,
std::chrono::seconds(1));
}
void XkcdRequestHandlerFactory::onServerStop() noexcept {
}
RequestHandler *XkcdRequestHandlerFactory::onRequest(RequestHandler *handler, HTTPMessage *message) noexcept {
std::string path = message->getPath();
Validations::sanitize_path(path);
if (boost::starts_with(path, _mount_path)) {
return new XkcdRequestHandler(_mount_path, timer->_timer.get());;
}
return handler;
}
XkcdRequestHandlerFactory::XkcdRequestHandlerFactory(const std::string &_mount_path)
: _mount_path(_mount_path) {}
}