From dcb7b6aae07ea117df8247cdba09ee1510f86606 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 16 Dec 2019 15:12:26 +0800 Subject: [PATCH] Refactor HTTP Message by decoupling with http_parser --- trunk/src/protocol/srs_http_stack.hpp | 3 - trunk/src/service/srs_service_http_conn.cpp | 66 ++++++++++----------- trunk/src/service/srs_service_http_conn.hpp | 27 +++++---- trunk/src/utest/srs_utest_http.cpp | 4 ++ 4 files changed, 52 insertions(+), 48 deletions(-) diff --git a/trunk/src/protocol/srs_http_stack.hpp b/trunk/src/protocol/srs_http_stack.hpp index a59b26230..e27978df3 100644 --- a/trunk/src/protocol/srs_http_stack.hpp +++ b/trunk/src/protocol/srs_http_stack.hpp @@ -428,9 +428,6 @@ public: virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); }; -// For http header. -typedef std::pair SrsHttpHeaderField; - // A Request represents an HTTP request received by a server // or to be sent by a client. // diff --git a/trunk/src/service/srs_service_http_conn.cpp b/trunk/src/service/srs_service_http_conn.cpp index 698d4b4a1..8525390b6 100644 --- a/trunk/src/service/srs_service_http_conn.cpp +++ b/trunk/src/service/srs_service_http_conn.cpp @@ -90,10 +90,14 @@ srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** p } // create msg - SrsHttpMessage* msg = new SrsHttpMessage(reader); + SrsHttpMessage* msg = new SrsHttpMessage(reader, buffer); + + // Initialize the basic information. + bool keep_alive = http_should_keep_alive(&header); + msg->set_basic(header.method, header.status_code, header.content_length, keep_alive); // initalize http msg, parse url. - if ((err = msg->update(url, jsonp, &header, buffer, headers)) != srs_success) { + if ((err = msg->update(url, jsonp, headers)) != srs_success) { srs_freep(msg); return srs_error_wrap(err, "update message"); } @@ -253,16 +257,21 @@ int SrsHttpParser::on_body(http_parser* parser, const char* at, size_t length) return 0; } -SrsHttpMessage::SrsHttpMessage(ISrsReader* reader) : ISrsHttpMessage() +SrsHttpMessage::SrsHttpMessage(ISrsReader* reader, SrsFastStream* buffer) : ISrsHttpMessage() { owner_conn = NULL; chunked = false; infinite_chunked = false; - keep_alive = true; _uri = new SrsHttpUri(); - _body = new SrsHttpResponseReader(this, reader); + _body = new SrsHttpResponseReader(this, reader, buffer); _http_ts_send_buffer = new char[SRS_HTTP_TS_SEND_BUFFER_SIZE]; + jsonp = false; + + _method = 0; + _status = 0; + _content_length = 0; + _keep_alive = true; } SrsHttpMessage::~SrsHttpMessage() @@ -272,26 +281,25 @@ SrsHttpMessage::~SrsHttpMessage() srs_freepa(_http_ts_send_buffer); } -srs_error_t SrsHttpMessage::update(string url, bool allow_jsonp, http_parser* header, SrsFastStream* body, vector& headers) +void SrsHttpMessage::set_basic(uint8_t method, uint16_t status, int64_t content_length, bool keep_alive) +{ + _method = method; + _status = status; + _content_length = content_length; + _keep_alive = keep_alive; +} + +srs_error_t SrsHttpMessage::update(string url, bool allow_jsonp, vector& headers) { srs_error_t err = srs_success; _url = url; - _header = *header; _headers = headers; // whether chunked. std::string transfer_encoding = get_request_header("Transfer-Encoding"); chunked = (transfer_encoding == "chunked"); - // whether keep alive. - keep_alive = http_should_keep_alive(header); - - // set the buffer. - if ((err = _body->initialize(body)) != srs_success) { - return srs_error_wrap(err, "init body"); - } - // parse uri from url. std::string host = get_request_header("Host"); @@ -349,13 +357,13 @@ uint8_t SrsHttpMessage::method() return SRS_CONSTS_HTTP_DELETE; } } - - return (uint8_t)_header.method; + + return _method; } uint16_t SrsHttpMessage::status_code() { - return (uint16_t)_header.status_code; + return _status; } string SrsHttpMessage::method_str() @@ -405,7 +413,7 @@ bool SrsHttpMessage::is_http_delete() bool SrsHttpMessage::is_http_options() { - return _header.method == SRS_CONSTS_HTTP_OPTIONS; + return _method == SRS_CONSTS_HTTP_OPTIONS; } bool SrsHttpMessage::is_chunked() @@ -415,7 +423,7 @@ bool SrsHttpMessage::is_chunked() bool SrsHttpMessage::is_keep_alive() { - return keep_alive; + return _keep_alive; } bool SrsHttpMessage::is_infinite_chunked() @@ -524,7 +532,7 @@ ISrsHttpResponseReader* SrsHttpMessage::body_reader() int64_t SrsHttpMessage::content_length() { - return _header.content_length; + return _content_length; } string SrsHttpMessage::query_get(string key) @@ -865,32 +873,20 @@ srs_error_t SrsHttpResponseWriter::send_header(char* data, int size) return skt->write((void*)buf.c_str(), buf.length(), NULL); } -SrsHttpResponseReader::SrsHttpResponseReader(SrsHttpMessage* msg, ISrsReader* reader) +SrsHttpResponseReader::SrsHttpResponseReader(SrsHttpMessage* msg, ISrsReader* reader, SrsFastStream* body) { skt = reader; owner = msg; is_eof = false; nb_total_read = 0; nb_left_chunk = 0; - buffer = NULL; + buffer = body; } SrsHttpResponseReader::~SrsHttpResponseReader() { } -srs_error_t SrsHttpResponseReader::initialize(SrsFastStream* body) -{ - srs_error_t err = srs_success; - - nb_chunk = 0; - nb_left_chunk = 0; - nb_total_read = 0; - buffer = body; - - return err; -} - bool SrsHttpResponseReader::eof() { return is_eof; diff --git a/trunk/src/service/srs_service_http_conn.hpp b/trunk/src/service/srs_service_http_conn.hpp index 4ac4d043f..da40ccea5 100644 --- a/trunk/src/service/srs_service_http_conn.hpp +++ b/trunk/src/service/srs_service_http_conn.hpp @@ -37,6 +37,9 @@ class ISrsReader; class SrsHttpResponseReader; class ISrsProtocolReadWriter; +// For http header. +typedef std::pair SrsHttpHeaderField; + // A wrapper for http-parser, // provides HTTP message originted service. class SrsHttpParser @@ -101,8 +104,6 @@ private: std::string _url; // The extension of file, for example, .flv std::string _ext; - // parsed http header. - http_parser _header; // The body object, reader object. // @remark, user can get body in string by get_body(). SrsHttpResponseReader* _body; @@ -110,8 +111,6 @@ private: bool chunked; // Whether the body is infinite chunked. bool infinite_chunked; - // Whether the request indicates should keep alive for the http connection. - bool keep_alive; // The uri parser SrsHttpUri* _uri; // Use a buffer to read and send ts file. @@ -123,16 +122,25 @@ private: std::map _query; // The transport connection, can be NULL. SrsConnection* owner_conn; +private: + uint8_t _method; + uint16_t _status; + int64_t _content_length; + // Whether the request indicates should keep alive for the http connection. + bool _keep_alive; +private: // Whether request is jsonp. bool jsonp; // The method in QueryString will override the HTTP method. std::string jsonp_method; public: - SrsHttpMessage(ISrsReader* io); + SrsHttpMessage(ISrsReader* reader, SrsFastStream* buffer); virtual ~SrsHttpMessage(); public: + // Set the basic information for HTTP request. + virtual void set_basic(uint8_t method, uint16_t status, int64_t content_length, bool keep_alive); // set the original messages, then update the message. - virtual srs_error_t update(std::string url, bool allow_jsonp, http_parser* header, SrsFastStream* body, std::vector& headers); + virtual srs_error_t update(std::string url, bool allow_jsonp, std::vector& headers); public: // Get the owner connection, maybe NULL. virtual SrsConnection* connection(); @@ -261,11 +269,10 @@ private: // Already read total bytes. int64_t nb_total_read; public: - SrsHttpResponseReader(SrsHttpMessage* msg, ISrsReader* reader); + // Generally the reader is the under-layer io such as socket, + // while buffer is a fast cache which may have cached some data from reader. + SrsHttpResponseReader(SrsHttpMessage* msg, ISrsReader* reader, SrsFastStream* buffer); virtual ~SrsHttpResponseReader(); -public: - // Initialize the response reader with buffer. - virtual srs_error_t initialize(SrsFastStream* buffer); // Interface ISrsHttpResponseReader public: virtual bool eof(); diff --git a/trunk/src/utest/srs_utest_http.cpp b/trunk/src/utest/srs_utest_http.cpp index 21a856de6..fe1a3e865 100644 --- a/trunk/src/utest/srs_utest_http.cpp +++ b/trunk/src/utest/srs_utest_http.cpp @@ -153,3 +153,7 @@ VOID TEST(ProtocolHTTPTest, HTTPHeader) h.set_content_type("text/plain"); EXPECT_STREQ("text/plain", h.content_type().c_str()); } + +VOID TEST(ProtocolHTTPTest, HTTPCommonHandler) +{ +}