Arquivos
hhvm/hphp/runtime/base/server/server.h
T
Adam Simpkins ee27bfa147 refactor RequestHandler behavior
This refactors the RequestHandler code, to decouple RequestHandler
behavior from the Server implementation.  The goal is to make it easier
to define additional Server implementations, in addition to just
LibEventServer.

This adds a RequestHandlerFactory function, rather than using a pure
virtual method of the Server class.  With the old model, you had to
subclass each server implementation separately for each RequestHandler
type you wanted to use, resulting in NxM classes if you have N server
types and M request handler types.

This also changes the behavior of the RequestHandler class somewhat:
the code now only creates a single RequestHandler per thread, and uses
that object for all request in that thread.  Previously the
LibEventServer code would attempt to create a new RequestHandler object
for each request if supportReset() returned true.  This was used by
RPCRequestHandler.  Now the RPCRequestHandler instead just resets itself
automatically when necessary, without requiring external help from
LibEventServer.

contbuild test runs failed due to git server issues.
2013-06-03 23:54:39 -07:00

258 linhas
7.0 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_HTTP_SERVER_SERVER_H_
#define incl_HPHP_HTTP_SERVER_SERVER_H_
#include "hphp/runtime/base/server/transport.h"
#include "hphp/util/exception.h"
#include "hphp/util/lock.h"
#include <memory>
/**
* (1) For people who want to quickly come up with an HTTP server handling
* their specific requests, we really want to minimize writing an HTTP
* server to something like this,
*
* class MyRequestHandler : public RequestHandler {
* public:
* virtual void handleRequest(Transport *transport) {
* // ...
* }
* };
*
* Then, run a server like this,
*
* ServerPtr server = make_shared<LibEventServer>("127.0.0.1", 80, 20);
* server->setRequestHandlerFactory<MyRequestHandler>();
* Server::InstallStopSignalHandlers(server);
* server->start();
*
* This way, we can easily swap out an implementation like LibEventServer
* without any modifications to MyRequestHandler, if LibEventServer model
* doesn't perform well with the specific requests.
*
* (2) For people who are interested in implementing a high-performance HTTP
* server, derive a new class from Server just like LibEventServer
* does.
*
* class MyTransport : public Transport {
* // implements transport-related functions
* };
*
* class MyServer : public Server {
* // implements how to start/stop a server
* };
*
* (3) LibEventServer is pre-implemented with evhttp, and it has one thread
* listening on a socket and dispatching jobs to multiple worker threads.
*
*/
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Server);
/**
* Base class of an HTTP request handler. Defining minimal interface an
* HTTP request handler needs to implement.
*
* Note that each request handler may be invoked multiple times for different
* requests.
*/
class RequestHandler {
public:
virtual ~RequestHandler() {}
/**
* Sub-class handles a request by implementing this function.
*/
virtual void handleRequest(Transport *transport) = 0;
};
typedef std::function<std::unique_ptr<RequestHandler>()> RequestHandlerFactory;
/**
* Base class of an HTTP server. Defining minimal interface an HTTP server
* needs to implement.
*/
class Server {
public:
enum RunStatus {
NOT_YET_STARTED = 0,
RUNNING,
STOPPING,
STOPPED,
};
/**
* Whether to turn on full stacktrace on internal server errors. Default is
* true.
*/
static bool StackTraceOnError;
/**
* ...so that we can grarefully stop these servers on signals.
*/
static void InstallStopSignalHandlers(ServerPtr server);
public:
/**
* Constructor.
*/
Server(const std::string &address, int port, int threadCount);
/**
* Set the RequestHandlerFactory that this server will use.
* This must be called before start().
*/
void setRequestHandlerFactory(RequestHandlerFactory f) {
m_handlerFactory = f;
}
/**
* Helper function to set the RequestHandlerFactory to a
* GenericRequestHandlerFactory for the specified handler type.
*/
template<class TRequestHandler>
void setRequestHandlerFactory() {
setRequestHandlerFactory([] {
return std::unique_ptr<RequestHandler>(new TRequestHandler());
});
}
/**
* Informational.
*/
std::string getAddress() const { return m_address;}
int getPort() const { return m_port;}
int getThreadCount() const { return m_threadCount;}
RunStatus getStatus() const {
return m_status;
}
void setStatus(RunStatus status) {
m_status = status;
}
/**
* Destructor.
*/
virtual ~Server() {}
/**
* Start this web server. Note this is a non-blocking call.
*/
virtual void start() = 0;
/**
* Block until web server is stopped.
*/
virtual void waitForEnd() = 0;
/**
* Gracefully stop this web server. We will stop accepting new connections
* and finish ongoing requests without being interrupted in the middle of
* them. Note this is a non-blocking call and it will return immediately.
* At background, it will eventually make the thread calling start() quit.
*/
virtual void stop() = 0;
/**
* How many threads are actively working on handling requests.
*/
virtual int getActiveWorker() = 0;
/**
* How many jobs are queued waiting to be handled.
*/
virtual int getQueuedJobs() = 0;
virtual int getLibEventConnectionCount() = 0;
/**
* Create a new RequestHandler.
*/
std::unique_ptr<RequestHandler> createRequestHandler() {
return m_handlerFactory();
}
/**
* Overwrite for URL blocking.
*/
virtual bool shouldHandle(const std::string &cmd);
/**
* To enable SSL of the current server, it will listen to an additional
* port as specified in parameter.
*/
virtual bool enableSSL(void *sslCTX, int port) = 0;
protected:
std::string m_address;
int m_port;
int m_threadCount;
mutable Mutex m_mutex;
RequestHandlerFactory m_handlerFactory;
private:
RunStatus m_status;
};
/**
* All exceptions Server throws should derive from this base class.
*/
class ServerException : public Exception {
public:
ServerException(const char *fmt, ...) {
va_list ap; va_start(ap, fmt); format(fmt, ap); va_end(ap);
}
};
class FailedToListenException : public ServerException {
public:
FailedToListenException(const std::string &addr, int port)
: ServerException("Failed to listen on %s:%d", addr.c_str(), port) {
}
};
class InvalidUrlException : public ServerException {
public:
explicit InvalidUrlException(const char *part)
: ServerException("Invalid URL: %s", part) {
}
};
class InvalidMethodException : public ServerException {
public:
explicit InvalidMethodException(const char *msg)
: ServerException("Invalid method: %s", msg) {
}
};
class InvalidHeaderException : public ServerException {
public:
InvalidHeaderException(const char *name, const char *value)
: ServerException("Invalid header: %s: %s", name, value) {
}
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_HTTP_SERVER_SERVER_H_