proxygen
ScopedHTTPServer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
10 #pragma once
11 
12 #include <boost/thread.hpp>
17 
18 namespace proxygen {
19 
20 template <typename HandlerType>
21 class ScopedHandler : public RequestHandler {
22  public:
23  explicit ScopedHandler(HandlerType* ptr): handlerPtr_(ptr) {
24  }
25 
26  void onRequest(std::unique_ptr<HTTPMessage> headers) noexcept override {
27  request_ = std::move(headers);
28  }
29 
30  void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {
32  }
33 
35 
36  void onEOM() noexcept override {
37  try {
39  (*handlerPtr_)(*request_, requestBody_.move(), r);
40  r.sendWithEOM();
41  } catch (const std::exception& ex) {
43  .status(500, "Internal Server Error")
44  .body(ex.what())
45  .sendWithEOM();
46  } catch (...) {
48  .status(500, "Internal Server Error")
49  .body("Unknown exception thrown")
50  .sendWithEOM();
51  }
52  }
53 
54  void requestComplete() noexcept override { delete this; }
55 
56  void onError(ProxygenError) noexcept override { delete this; }
57  private:
58  HandlerType* const handlerPtr_{nullptr};
59 
60  std::unique_ptr<HTTPMessage> request_;
62 };
63 
64 template <typename HandlerType>
66  public:
67  explicit ScopedHandlerFactory(HandlerType handler): handler_(handler) {
68  }
69 
71  }
72 
73  void onServerStop() noexcept override {
74  }
75 
77  return new ScopedHandler<HandlerType>(&handler_);
78  }
79  private:
80  HandlerType handler_;
81 };
82 
88 class ScopedHTTPServer final {
89  public:
94  template <typename HandlerType>
95  static std::unique_ptr<ScopedHTTPServer> start(
96  HandlerType handler,
97  int port = 0,
98  int numThreads = 4,
99  std::unique_ptr<wangle::SSLContextConfig> sslCfg = nullptr);
100 
104  static std::unique_ptr<ScopedHTTPServer> start(
106 
111  int getPort() const {
112  return getAddresses()[0].address.getPort();
113  }
114 
118  std::vector<HTTPServer::IPConfig> getAddresses() const {
119  auto addresses = server_->addresses();
120  CHECK(!addresses.empty());
121  return addresses;
122  }
123 
125  server_->stop();
126  thread_.join();
127  }
128 
129  private:
130  ScopedHTTPServer(std::thread thread,
131  std::unique_ptr<HTTPServer> server)
132  : thread_(std::move(thread)),
133  server_(std::move(server)) {
134  }
135 
136  std::thread thread_;
137  std::unique_ptr<HTTPServer> server_;
138 };
139 
140 template <typename HandlerType>
141 inline std::unique_ptr<ScopedHTTPServer> ScopedHTTPServer::start(
142  HandlerType handler,
143  int port,
144  int numThreads,
145  std::unique_ptr<wangle::SSLContextConfig> sslCfg) {
146 
147  std::unique_ptr<RequestHandlerFactory> f =
148  std::make_unique<ScopedHandlerFactory<HandlerType>>(handler);
149  return start(std::move(f), port, numThreads, std::move(sslCfg));
150 }
151 
152 template <>
153 inline std::unique_ptr<ScopedHTTPServer>
154 ScopedHTTPServer::start<std::unique_ptr<RequestHandlerFactory>>(
155  std::unique_ptr<RequestHandlerFactory> f,
156  int port,
157  int numThreads,
158  std::unique_ptr<wangle::SSLContextConfig> sslCfg) {
159  // This will handle both IPv4 and IPv6 cases
161  addr.setFromLocalPort(port);
162 
164  addr,
166  };
167 
168  if (sslCfg) {
169  cfg.sslConfigs.push_back(*sslCfg);
170  }
171 
172  HTTPServerOptions options;
173  options.threads = numThreads;
174  options.handlerFactories.push_back(std::move(f));
175  return start(std::move(cfg), std::move(options));
176 }
177 
178 inline std::unique_ptr<ScopedHTTPServer>
181  HTTPServerOptions options) {
182 
183  std::vector<HTTPServer::IPConfig> IPs = { std::move(cfg) };
184 
185  auto server = std::make_unique<HTTPServer>(std::move(options));
186  server->bind(IPs);
187 
188  // Start the server
189  std::exception_ptr eptr;
190  auto barrier = std::make_shared<boost::barrier>(2);
191 
192  std::thread t = std::thread([&, barrier] () {
193  server->start(
194  [&, barrier] () {
195  folly::setThreadName("http-acceptor");
196  barrier->wait();
197  },
198  [&, barrier] (std::exception_ptr ex) {
199  eptr = ex;
200  barrier->wait();
201  });
202  });
203 
204  // Wait for server to start
205  barrier->wait();
206  if (eptr) {
207  t.join();
208 
209  std::rethrow_exception(eptr);
210  }
211 
212  return std::unique_ptr<ScopedHTTPServer>(
213  new ScopedHTTPServer(std::move(t), std::move(server)));
214 }
215 
216 }
void * ptr
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
Definition: IOBufQueue.cpp:143
folly::IOBufQueue requestBody_
auto f
ResponseBuilder & status(uint16_t code, const std::string &message)
void setFromLocalPort(uint16_t port)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
std::unique_ptr< folly::IOBuf > move()
Definition: IOBufQueue.h:459
ResponseBuilder & body(std::unique_ptr< folly::IOBuf > bodyIn)
requires E e noexcept(noexcept(s.error(std::move(e))))
ScopedHandler(HandlerType *ptr)
std::unique_ptr< HTTPServer > server_
void handler(int, siginfo_t *, void *)
void onBody(std::unique_ptr< folly::IOBuf > body) noexceptoverride
ScopedHTTPServer(std::thread thread, std::unique_ptr< HTTPServer > server)
std::vector< std::unique_ptr< RequestHandlerFactory > > handlerFactories
RequestHandler * onRequest(RequestHandler *, HTTPMessage *) noexceptoverride
void requestComplete() noexceptoverride
void onRequest(std::unique_ptr< HTTPMessage > headers) noexceptoverride
static std::unique_ptr< ScopedHTTPServer > start(HandlerType handler, int port=0, int numThreads=4, std::unique_ptr< wangle::SSLContextConfig > sslCfg=nullptr)
void onError(ProxygenError) noexceptoverride
void onServerStart(folly::EventBase *) noexceptoverride
auto start
std::vector< HTTPServer::IPConfig > getAddresses() const
bool setThreadName(std::thread::id tid, StringPiece name)
Definition: ThreadName.cpp:109
std::unique_ptr< HTTPMessage > request_
HandlerType *const handlerPtr_
ScopedHandlerFactory(HandlerType handler)
void onEOM() noexceptoverride
void onServerStop() noexceptoverride
void onUpgrade(proxygen::UpgradeProtocol) noexceptoverride
ResponseHandler * downstream_
ThreadPoolListHook * addr