187 lines
4.8 KiB
C
187 lines
4.8 KiB
C
|
#ifndef HV_HTTP_HANDLER_H_
|
||
|
#define HV_HTTP_HANDLER_H_
|
||
|
|
||
|
#include "HttpService.h"
|
||
|
#include "HttpParser.h"
|
||
|
#include "FileCache.h"
|
||
|
|
||
|
#include "WebSocketServer.h"
|
||
|
#include "WebSocketParser.h"
|
||
|
|
||
|
class HttpHandler {
|
||
|
public:
|
||
|
enum ProtocolType {
|
||
|
UNKNOWN,
|
||
|
HTTP_V1,
|
||
|
HTTP_V2,
|
||
|
WEBSOCKET,
|
||
|
} protocol;
|
||
|
|
||
|
enum State {
|
||
|
WANT_RECV,
|
||
|
HANDLE_BEGIN,
|
||
|
HANDLE_CONTINUE,
|
||
|
HANDLE_END,
|
||
|
WANT_SEND,
|
||
|
SEND_HEADER,
|
||
|
SEND_BODY,
|
||
|
SEND_DONE,
|
||
|
WANT_CLOSE,
|
||
|
} state;
|
||
|
|
||
|
// errno
|
||
|
int error;
|
||
|
|
||
|
// flags
|
||
|
unsigned ssl :1;
|
||
|
unsigned keepalive :1;
|
||
|
unsigned upgrade :1;
|
||
|
unsigned proxy :1;
|
||
|
unsigned proxy_connected :1;
|
||
|
unsigned forward_proxy :1;
|
||
|
unsigned reverse_proxy :1;
|
||
|
|
||
|
// peeraddr
|
||
|
char ip[64];
|
||
|
int port;
|
||
|
|
||
|
// for log
|
||
|
long pid;
|
||
|
long tid;
|
||
|
|
||
|
// for http
|
||
|
hio_t *io;
|
||
|
HttpService *service;
|
||
|
HttpRequestPtr req;
|
||
|
HttpResponsePtr resp;
|
||
|
HttpResponseWriterPtr writer;
|
||
|
HttpParserPtr parser;
|
||
|
HttpContextPtr ctx;
|
||
|
http_handler* api_handler;
|
||
|
|
||
|
// for GetSendData
|
||
|
std::string header;
|
||
|
// std::string body;
|
||
|
|
||
|
// for websocket
|
||
|
WebSocketService* ws_service;
|
||
|
WebSocketChannelPtr ws_channel;
|
||
|
WebSocketParserPtr ws_parser;
|
||
|
uint64_t last_send_ping_time;
|
||
|
uint64_t last_recv_pong_time;
|
||
|
|
||
|
// for sendfile
|
||
|
FileCache *files;
|
||
|
file_cache_ptr fc; // cache small file
|
||
|
struct LargeFile : public HFile {
|
||
|
HBuf buf;
|
||
|
uint64_t timer;
|
||
|
} *file; // for large file
|
||
|
|
||
|
// for proxy
|
||
|
std::string proxy_host;
|
||
|
int proxy_port;
|
||
|
|
||
|
HttpHandler(hio_t* io = NULL);
|
||
|
~HttpHandler();
|
||
|
|
||
|
bool Init(int http_version = 1);
|
||
|
void Reset();
|
||
|
void Close();
|
||
|
|
||
|
/* @workflow:
|
||
|
* HttpServer::on_recv -> HttpHandler::FeedRecvData -> Init -> HttpParser::InitRequest -> HttpRequest::http_cb ->
|
||
|
* onHeadersComplete -> proxy ? handleProxy -> connectProxy :
|
||
|
* onMessageComplete -> upgrade ? handleUpgrade : HandleHttpRequest -> HttpParser::SubmitResponse ->
|
||
|
* SendHttpResponse -> while(GetSendData) hio_write ->
|
||
|
* keepalive ? Reset : Close -> hio_close
|
||
|
*
|
||
|
* @return
|
||
|
* == len: ok
|
||
|
* == 0: WANT_CLOSE
|
||
|
* < 0: error
|
||
|
*/
|
||
|
int FeedRecvData(const char* data, size_t len);
|
||
|
|
||
|
/* @workflow:
|
||
|
* preprocessor -> middleware -> processor -> postprocessor
|
||
|
*
|
||
|
* @return status_code
|
||
|
* == 0: HANDLE_CONTINUE
|
||
|
* != 0: HANDLE_END
|
||
|
*/
|
||
|
int HandleHttpRequest();
|
||
|
|
||
|
int GetSendData(char** data, size_t* len);
|
||
|
|
||
|
int SendHttpResponse(bool submit = true);
|
||
|
int SendHttpStatusResponse(http_status status_code);
|
||
|
|
||
|
// HTTP2
|
||
|
bool SwitchHTTP2();
|
||
|
|
||
|
// websocket
|
||
|
bool SwitchWebSocket();
|
||
|
void WebSocketOnOpen() {
|
||
|
ws_channel->status = hv::SocketChannel::CONNECTED;
|
||
|
if (ws_service && ws_service->onopen) {
|
||
|
ws_service->onopen(ws_channel, req);
|
||
|
}
|
||
|
}
|
||
|
void WebSocketOnClose() {
|
||
|
ws_channel->status = hv::SocketChannel::DISCONNECTED;
|
||
|
if (ws_service && ws_service->onclose) {
|
||
|
ws_service->onclose(ws_channel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int SetError(int error_code, http_status status_code = HTTP_STATUS_BAD_REQUEST) {
|
||
|
error = error_code;
|
||
|
if (resp) resp->status_code = status_code;
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
const HttpContextPtr& context();
|
||
|
int handleRequestHeaders();
|
||
|
// Expect: 100-continue
|
||
|
void handleExpect100();
|
||
|
void addResponseHeaders();
|
||
|
|
||
|
// http_cb
|
||
|
void onHeadersComplete();
|
||
|
void onBody(const char* data, size_t size);
|
||
|
void onMessageComplete();
|
||
|
|
||
|
// default handlers
|
||
|
int defaultRequestHandler();
|
||
|
int defaultStaticHandler();
|
||
|
int defaultLargeFileHandler();
|
||
|
int defaultErrorHandler();
|
||
|
int customHttpHandler(const http_handler& handler);
|
||
|
int invokeHttpHandler(const http_handler* handler);
|
||
|
|
||
|
// sendfile
|
||
|
int openFile(const char* filepath);
|
||
|
int sendFile();
|
||
|
void closeFile();
|
||
|
bool isFileOpened();
|
||
|
|
||
|
// upgrade
|
||
|
int handleUpgrade(const char* upgrade_protocol);
|
||
|
int upgradeWebSocket();
|
||
|
int upgradeHTTP2();
|
||
|
|
||
|
// proxy
|
||
|
int handleProxy();
|
||
|
int handleForwardProxy();
|
||
|
int handleReverseProxy();
|
||
|
int connectProxy(const std::string& url);
|
||
|
int closeProxy();
|
||
|
int sendProxyRequest();
|
||
|
static void onProxyConnect(hio_t* upstream_io);
|
||
|
static void onProxyClose(hio_t* upstream_io);
|
||
|
};
|
||
|
|
||
|
#endif // HV_HTTP_HANDLER_H_
|