comment out unused parameters
[hiphop-php.git] / hphp / runtime / server / server.h
blob59e4080a3da646528ab0df585da76299c33fe122
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 assert(m_maxThreads >= 0);
326 if (m_initThreads < 0 || m_initThreads > m_maxThreads) {
327 m_initThreads = m_maxThreads;
331 std::string m_address;
332 uint16_t m_port;
333 int m_maxThreads;
334 int m_initThreads;
335 int m_serverFD;
336 int m_sslFD;
337 std::string m_takeoverFilename;
338 bool m_useFileSocket;
339 int m_queueToWorkerRatio;
343 * A ServerFactory knows how to create Server objects.
345 struct ServerFactory {
346 ServerFactory() {}
347 virtual ~ServerFactory() {}
349 ServerFactory(const ServerFactory&) = delete;
350 ServerFactory& operator=(const ServerFactory&) = delete;
352 virtual ServerPtr createServer(const ServerOptions &options) = 0;
354 ServerPtr createServer(const std::string &address,
355 uint16_t port,
356 int maxThreads,
357 int initThreads = -1);
361 * A registry mapping server type names to ServerFactory objects.
363 * This allows new server types to be plugged in dynamically, without having to
364 * hard code the list of all possible server types.
366 struct ServerFactoryRegistry {
367 ServerFactoryRegistry();
369 ServerFactoryRegistry(const ServerFactoryRegistry&) = delete;
370 ServerFactoryRegistry& operator=(const ServerFactoryRegistry&) = delete;
372 static ServerFactoryRegistry *getInstance();
374 static ServerPtr createServer(const std::string &type,
375 const std::string &address,
376 uint16_t port,
377 int maxThreads,
378 int initThreads = -1);
380 void registerFactory(const std::string &name,
381 const ServerFactoryPtr &factory);
383 ServerFactoryPtr getFactory(const std::string &name);
385 private:
386 Mutex m_lock;
387 std::map<std::string, ServerFactoryPtr> m_factories;
391 * All exceptions Server throws should derive from this base class.
393 struct ServerException : Exception {
394 ServerException(ATTRIBUTE_PRINTF_STRING const char *fmt, ...)
395 ATTRIBUTE_PRINTF(2,3);
398 struct FailedToListenException : ServerException {
399 explicit FailedToListenException(const std::string &addr)
400 : ServerException("Failed to listen to unix socket at %s", addr.c_str()) {
402 FailedToListenException(const std::string &addr, int port)
403 : ServerException("Failed to listen on %s:%d", addr.c_str(), port) {
407 struct InvalidUrlException : ServerException {
408 explicit InvalidUrlException(const char *part)
409 : ServerException("Invalid URL: %s", part) {
413 struct InvalidMethodException : ServerException {
414 explicit InvalidMethodException(const char *msg)
415 : ServerException("Invalid method: %s", msg) {
419 struct InvalidHeaderException : ServerException {
420 InvalidHeaderException(const char *name, const char *value)
421 : ServerException("Invalid header: %s: %s", name, value) {
425 ///////////////////////////////////////////////////////////////////////////////
428 #endif // incl_HPHP_HTTP_SERVER_SERVER_H_