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();
 | 
						|
    void  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_
 |