Codemod asserts to assertxs in the runtime
[hiphop-php.git] / hphp / runtime / server / server.h
blobe8accac621162cb2e335a1812ccfc7d83a20f5f0
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_HTTP_SERVER_SERVER_H_
18 #define incl_HPHP_HTTP_SERVER_SERVER_H_
20 #include <algorithm>
21 #include <chrono>
22 #include <functional>
23 #include <list>
24 #include <memory>
25 #include <string>
27 #include "hphp/runtime/server/takeover-agent.h"
28 #include "hphp/runtime/server/transport.h"
29 #include "hphp/util/exception.h"
30 #include "hphp/util/health-monitor-types.h"
31 #include "hphp/util/lock.h"
33 /**
34 * (1) For people who want to quickly come up with an HTTP server handling
35 * their specific requests, we really want to minimize writing an HTTP
36 * server to something like this,
38 * struct MyRequestHandler : RequestHandler {
39 * virtual void handleRequest(Transport *transport) {
40 * // ...
41 * }
42 * };
44 * Then, run a server like this,
46 * auto server = std::make_shared<LibEventServer>("127.0.0.1", 80, 20);
47 * server->setRequestHandlerFactory<MyRequestHandler>();
48 * Server::InstallStopSignalHandlers(server);
49 * server->start();
51 * This way, we can easily swap out an implementation like LibEventServer
52 * without any modifications to MyRequestHandler, if LibEventServer model
53 * doesn't perform well with the specific requests.
55 * (2) For people who are interested in implementing a high-performance HTTP
56 * server, derive a new class from Server just like LibEventServer
57 * does.
59 * struct MyTransport : Transport {
60 * // implements transport-related functions
61 * };
63 * struct MyServer : Server {
64 * // implements how to start/stop a server
65 * };
67 * (3) LibEventServer is pre-implemented with evhttp, and it has one thread
68 * listening on a socket and dispatching jobs to multiple worker threads.
72 namespace HPHP {
73 ///////////////////////////////////////////////////////////////////////////////
75 struct Server;
76 struct ServerFactory;
77 using ServerPtr = std::unique_ptr<Server>;
78 using ServerFactoryPtr = std::shared_ptr<ServerFactory>;
80 /**
81 * Base class of an HTTP request handler. Defining minimal interface an
82 * HTTP request handler needs to implement.
84 * Note that each request handler may be invoked multiple times for different
85 * requests.
87 struct RequestHandler {
88 explicit RequestHandler(int timeout) : m_timeout(timeout) {}
89 virtual ~RequestHandler() {}
91 /**
92 * Called before and after request-handling work.
94 virtual void setupRequest(Transport* /*transport*/) {}
95 virtual void teardownRequest(Transport* /*transport*/) noexcept {}
97 /**
98 * Sub-class handles a request by implementing this function.
100 virtual void handleRequest(Transport* transport) = 0;
103 * Sub-class handles a request by implementing this function. This is called
104 * when the server determines this request should not be processed (e.g., due
105 * to timeout).
107 virtual void abortRequest(Transport* transport) = 0;
110 * Convenience wrapper around {setup,handle,teardown}Request().
112 void run(Transport* transport) {
113 SCOPE_EXIT { teardownRequest(transport); };
114 setupRequest(transport);
115 handleRequest(transport);
119 * Write an entry to the handler's access log.
121 virtual void logToAccessLog(Transport* /*transport*/) {}
123 int getDefaultTimeout() const { return m_timeout; }
125 private:
126 int m_timeout;
129 using RequestHandlerFactory = std::function<std::unique_ptr<RequestHandler>()>;
130 using URLChecker = std::function<bool(const std::string&)>;
133 * Base class of an HTTP server. Defining minimal interface an HTTP server
134 * needs to implement.
136 struct Server : IHostHealthObserver {
137 enum class RunStatus {
138 NOT_YET_STARTED = 0,
139 RUNNING,
140 STOPPING,
141 STOPPED,
145 * Whether to turn on full stacktrace on internal server errors. Default is
146 * true.
148 static bool StackTraceOnError;
151 * ...so that we can grarefully stop these servers on signals.
153 static void InstallStopSignalHandlers(ServerPtr server);
155 public:
156 struct ServerEventListener {
157 virtual ~ServerEventListener() {}
158 virtual void serverStopped(Server* /*server*/) {}
161 Server(const std::string &address, int port);
164 * Set the RequestHandlerFactory that this server will use.
165 * This must be called before start().
167 void setRequestHandlerFactory(RequestHandlerFactory f) {
168 m_handlerFactory = f;
171 * Helper function to set the RequestHandlerFactory to a
172 * GenericRequestHandlerFactory for the specified handler type.
174 template<class TRequestHandler>
175 void setRequestHandlerFactory(int timeout) {
176 setRequestHandlerFactory([timeout] {
177 return std::unique_ptr<RequestHandler>(new TRequestHandler(timeout));
182 * Set the URLChecker function which determines which paths this server is
183 * allowed to server.
185 * Defaults to SatelliteServerInfo::checkURL()
187 void setUrlChecker(const URLChecker& checker) {
188 m_urlChecker = checker;
192 * Add or remove a ServerEventListener.
194 void addServerEventListener(ServerEventListener* listener) {
195 m_listeners.push_back(listener);
197 void removeServerEventListener(ServerEventListener* listener) {
198 auto it = std::find(m_listeners.begin(), m_listeners.end(), listener);
199 if (it != m_listeners.end()) {
200 m_listeners.erase(it);
205 * Add or remove a TakeoverListener to this server.
207 * This is a no-op for servers that do not support socket takeover.
209 virtual void addTakeoverListener(TakeoverListener* /*listener*/) {}
210 virtual void removeTakeoverListener(TakeoverListener* /*listener*/) {}
213 * Add additional worker threads
215 virtual void addWorkers(int numWorkers) = 0;
218 * Informational.
220 std::string getAddress() const { return m_address;}
221 int getPort() const { return m_port;}
223 RunStatus getStatus() const { return m_status;}
224 void setStatus(RunStatus status) { m_status = status;}
226 * IHostHealthObserver interface. Note that m_status doesn't
227 * contain server health information.
229 void notifyNewStatus(HealthLevel newLevel) override {
230 m_healthLevel = newLevel;
232 HealthLevel getHealthLevel() override {
233 return m_healthLevel;
237 * Destructor.
239 ~Server() override {}
242 * Start this web server. Note this is a non-blocking call.
244 virtual void start() = 0;
247 * Block until web server is stopped.
249 virtual void waitForEnd() = 0;
252 * Gracefully stop this web server. We will stop accepting new connections
253 * and finish ongoing requests without being interrupted in the middle of
254 * them. Note this is a non-blocking call and it will return immediately.
255 * At background, it will eventually make the thread calling start() quit.
257 virtual void stop() = 0;
260 * How many threads are actively working on handling requests.
262 virtual int getActiveWorker() = 0;
265 * How many jobs are queued waiting to be handled.
267 virtual int getQueuedJobs() = 0;
269 virtual int getLibEventConnectionCount() = 0;
272 * Create a new RequestHandler.
274 std::unique_ptr<RequestHandler> createRequestHandler() {
275 return m_handlerFactory();
279 * Check whether a request to the specified server path is allowed.
281 bool shouldHandle(const std::string &path) {
282 return m_urlChecker(path);
286 * To enable SSL of the current server, it will listen to an additional
287 * port as specified in parameter.
289 virtual bool enableSSL(int port) = 0;
292 * To enable SSL in addition to plaintext of the current server.
294 virtual bool enableSSLWithPlainText() {
295 return false;
298 protected:
299 std::string m_address;
300 int m_port;
301 mutable Mutex m_mutex;
302 RequestHandlerFactory m_handlerFactory;
303 URLChecker m_urlChecker;
304 std::list<ServerEventListener*> m_listeners;
306 private:
307 RunStatus m_status{RunStatus::NOT_YET_STARTED};
308 HealthLevel m_healthLevel{HealthLevel::Bold};
311 struct ServerOptions {
312 ServerOptions(const std::string &address,
313 uint16_t port,
314 int maxThreads,
315 int initThreads = -1)
316 : m_address(address),
317 m_port(port),
318 m_maxThreads(maxThreads),
319 m_initThreads(initThreads),
320 m_serverFD(-1),
321 m_sslFD(-1),
322 m_takeoverFilename(),
323 m_useFileSocket(false),
324 m_queueToWorkerRatio(1),
325 m_hugeThreads(0) {
326 assertx(m_maxThreads >= 0);
327 if (m_initThreads < 0 || m_initThreads > m_maxThreads) {
328 m_initThreads = m_maxThreads;
332 std::string m_address;
333 uint16_t m_port;
334 int m_maxThreads;
335 int m_initThreads;
336 int m_serverFD;
337 int m_sslFD;
338 std::string m_takeoverFilename;
339 bool m_useFileSocket;
340 int m_queueToWorkerRatio;
341 int m_hugeThreads;
345 * A ServerFactory knows how to create Server objects.
347 struct ServerFactory {
348 ServerFactory() {}
349 virtual ~ServerFactory() {}
351 ServerFactory(const ServerFactory&) = delete;
352 ServerFactory& operator=(const ServerFactory&) = delete;
354 virtual ServerPtr createServer(const ServerOptions &options) = 0;
356 ServerPtr createServer(const std::string &address,
357 uint16_t port,
358 int maxThreads,
359 int initThreads = -1);
363 * A registry mapping server type names to ServerFactory objects.
365 * This allows new server types to be plugged in dynamically, without having to
366 * hard code the list of all possible server types.
368 struct ServerFactoryRegistry {
369 ServerFactoryRegistry();
371 ServerFactoryRegistry(const ServerFactoryRegistry&) = delete;
372 ServerFactoryRegistry& operator=(const ServerFactoryRegistry&) = delete;
374 static ServerFactoryRegistry *getInstance();
376 static ServerPtr createServer(const std::string &type,
377 const std::string &address,
378 uint16_t port,
379 int maxThreads,
380 int initThreads = -1);
382 void registerFactory(const std::string &name,
383 const ServerFactoryPtr &factory);
385 ServerFactoryPtr getFactory(const std::string &name);
387 private:
388 Mutex m_lock;
389 std::map<std::string, ServerFactoryPtr> m_factories;
393 * All exceptions Server throws should derive from this base class.
395 struct ServerException : Exception {
396 ServerException(ATTRIBUTE_PRINTF_STRING const char *fmt, ...)
397 ATTRIBUTE_PRINTF(2,3);
400 struct FailedToListenException : ServerException {
401 explicit FailedToListenException(const std::string &addr)
402 : ServerException("Failed to listen to unix socket at %s", addr.c_str()) {
404 FailedToListenException(const std::string &addr, int port)
405 : ServerException("Failed to listen on %s:%d", addr.c_str(), port) {
409 struct InvalidUrlException : ServerException {
410 explicit InvalidUrlException(const char *part)
411 : ServerException("Invalid URL: %s", part) {
415 struct InvalidMethodException : ServerException {
416 explicit InvalidMethodException(const char *msg)
417 : ServerException("Invalid method: %s", msg) {
421 struct InvalidHeaderException : ServerException {
422 InvalidHeaderException(const char *name, const char *value)
423 : ServerException("Invalid header: %s: %s", name, value) {
427 ///////////////////////////////////////////////////////////////////////////////
430 #endif // incl_HPHP_HTTP_SERVER_SERVER_H_