Refactor header of HTTP message by using SrsHttpHeader.

pull/1568/head
winlin 5 years ago
parent dcb7b6aae0
commit ca2b68f428

@ -664,12 +664,7 @@ srs_error_t SrsGoApiRequests::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
// request headers // request headers
SrsJsonObject* headers = SrsJsonAny::object(); SrsJsonObject* headers = SrsJsonAny::object();
data->set("headers", headers); data->set("headers", headers);
r->header()->dumps(headers);
for (int i = 0; i < r->request_header_count(); i++) {
std::string key = r->request_header_key_at(i);
std::string value = r->request_header_value_at(i);
headers->set(key, SrsJsonAny::str(value.c_str()));
}
// server informations // server informations
SrsJsonObject* server = SrsJsonAny::object(); SrsJsonObject* server = SrsJsonAny::object();

@ -173,6 +173,20 @@ void SrsHttpHeader::del(string key)
} }
} }
int SrsHttpHeader::count()
{
return (int)headers.size();
}
void SrsHttpHeader::dumps(SrsJsonObject* o)
{
map<string, string>::iterator it;
for (it = headers.begin(); it != headers.end(); ++it) {
string v = it->second;
o->set(it->first, SrsJsonAny::str(v.c_str()));
}
}
int64_t SrsHttpHeader::content_length() int64_t SrsHttpHeader::content_length()
{ {
std::string cl = get("Content-Length"); std::string cl = get("Content-Length");
@ -776,13 +790,8 @@ srs_error_t SrsHttpCorsMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessag
// If CORS enabled, and there is a "Origin" header, it's CORS. // If CORS enabled, and there is a "Origin" header, it's CORS.
if (enabled) { if (enabled) {
for (int i = 0; i < r->request_header_count(); i++) { SrsHttpHeader* h = r->header();
string k = r->request_header_key_at(i); required = !h->get("Origin").empty();
if (k == "Origin" || k == "origin") {
required = true;
break;
}
}
} }
// When CORS required, set the CORS headers. // When CORS required, set the CORS headers.

@ -45,6 +45,7 @@ class SrsHttpHeader;
class ISrsHttpMessage; class ISrsHttpMessage;
class SrsHttpMuxEntry; class SrsHttpMuxEntry;
class ISrsHttpResponseWriter; class ISrsHttpResponseWriter;
class SrsJsonObject;
// From http specification // From http specification
// CR = <US-ASCII CR, carriage return (13)> // CR = <US-ASCII CR, carriage return (13)>
@ -129,6 +130,11 @@ public:
// Delete the http header indicated by key. // Delete the http header indicated by key.
// Return the removed header field. // Return the removed header field.
virtual void del(std::string); virtual void del(std::string);
// Get the count of headers.
virtual int count();
public:
// Dumps to a JSON object.
virtual void dumps(SrsJsonObject* o);
public: public:
// Get the content length. -1 if not set. // Get the content length. -1 if not set.
virtual int64_t content_length(); virtual int64_t content_length();
@ -505,9 +511,7 @@ public:
// then query_get("start") is "100", and query_get("end") is "200" // then query_get("start") is "100", and query_get("end") is "200"
virtual std::string query_get(std::string key) = 0; virtual std::string query_get(std::string key) = 0;
// Get the headers. // Get the headers.
virtual int request_header_count() = 0; virtual SrsHttpHeader* header() = 0;
virtual std::string request_header_key_at(int index) = 0;
virtual std::string request_header_value_at(int index) = 0;
public: public:
// Whether the current request is JSONP, // Whether the current request is JSONP,
// which has a "callback=xxx" in QueryString. // which has a "callback=xxx" in QueryString.

@ -39,11 +39,13 @@ using namespace std;
SrsHttpParser::SrsHttpParser() SrsHttpParser::SrsHttpParser()
{ {
buffer = new SrsFastStream(); buffer = new SrsFastStream();
header = NULL;
} }
SrsHttpParser::~SrsHttpParser() SrsHttpParser::~SrsHttpParser()
{ {
srs_freep(buffer); srs_freep(buffer);
srs_freep(header);
} }
srs_error_t SrsHttpParser::initialize(enum http_parser_type type, bool allow_jsonp) srs_error_t SrsHttpParser::initialize(enum http_parser_type type, bool allow_jsonp)
@ -70,19 +72,22 @@ srs_error_t SrsHttpParser::initialize(enum http_parser_type type, bool allow_jso
srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** ppmsg) srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** ppmsg)
{ {
*ppmsg = NULL;
srs_error_t err = srs_success; srs_error_t err = srs_success;
*ppmsg = NULL;
// reset request data. // Reset request data.
field_name = "";
field_value = "";
expect_field_name = true;
state = SrsHttpParseStateInit; state = SrsHttpParseStateInit;
header = http_parser(); hp_header = http_parser();
// Reset the message url.
url = ""; url = "";
headers.clear(); // The body that we have read from cache.
pbody = NULL; pbody = NULL;
// Reset the temporarily parsed header field.
expect_field_name = true;
// The header of the request.
srs_freep(header);
header = new SrsHttpHeader();
// do parse // do parse
if ((err = parse_message_imp(reader)) != srs_success) { if ((err = parse_message_imp(reader)) != srs_success) {
@ -93,11 +98,9 @@ srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** p
SrsHttpMessage* msg = new SrsHttpMessage(reader, buffer); SrsHttpMessage* msg = new SrsHttpMessage(reader, buffer);
// Initialize the basic information. // Initialize the basic information.
bool keep_alive = http_should_keep_alive(&header); msg->set_basic(hp_header.method, hp_header.status_code, hp_header.content_length);
msg->set_basic(header.method, header.status_code, header.content_length, keep_alive); msg->set_header(header, http_should_keep_alive(&hp_header));
if ((err = msg->set_url(url, jsonp)) != srs_success) {
// initalize http msg, parse url.
if ((err = msg->update(url, jsonp, headers)) != srs_success) {
srs_freep(msg); srs_freep(msg);
return srs_error_wrap(err, "update message"); return srs_error_wrap(err, "update message");
} }
@ -142,11 +145,6 @@ srs_error_t SrsHttpParser::parse_message_imp(ISrsReader* reader)
} }
} }
// parse last header.
if (!field_name.empty() && !field_value.empty()) {
headers.push_back(std::make_pair(field_name, field_value));
}
return err; return err;
} }
@ -167,7 +165,7 @@ int SrsHttpParser::on_headers_complete(http_parser* parser)
SrsHttpParser* obj = (SrsHttpParser*)parser->data; SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj); srs_assert(obj);
obj->header = *parser; obj->hp_header = *parser;
// save the parser when header parse completed. // save the parser when header parse completed.
obj->state = SrsHttpParseStateHeaderComplete; obj->state = SrsHttpParseStateHeaderComplete;
@ -196,7 +194,7 @@ int SrsHttpParser::on_url(http_parser* parser, const char* at, size_t length)
srs_assert(obj); srs_assert(obj);
if (length > 0) { if (length > 0) {
obj->url.append(at, (int)length); obj->url = string(at, (int)length);
} }
srs_info("Method: %d, Url: %.*s", parser->method, (int)length, at); srs_info("Method: %d, Url: %.*s", parser->method, (int)length, at);
@ -211,16 +209,12 @@ int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t l
// field value=>name, reap the field. // field value=>name, reap the field.
if (!obj->expect_field_name) { if (!obj->expect_field_name) {
obj->headers.push_back(std::make_pair(obj->field_name, obj->field_value)); obj->header->set(obj->field_name, obj->field_value);
// reset the field name when parsed.
obj->field_name = "";
obj->field_value = "";
} }
obj->expect_field_name = true; obj->expect_field_name = true;
if (length > 0) { if (length > 0) {
obj->field_name.append(at, (int)length); obj->field_name = string(at, (int)length);
} }
srs_info("Header field(%d bytes): %.*s", (int)length, (int)length, at); srs_info("Header field(%d bytes): %.*s", (int)length, (int)length, at);
@ -233,7 +227,7 @@ int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t l
srs_assert(obj); srs_assert(obj);
if (length > 0) { if (length > 0) {
obj->field_value.append(at, (int)length); obj->field_value = string(at, (int)length);
} }
obj->expect_field_name = false; obj->expect_field_name = false;
@ -281,38 +275,42 @@ SrsHttpMessage::~SrsHttpMessage()
srs_freepa(_http_ts_send_buffer); srs_freepa(_http_ts_send_buffer);
} }
void SrsHttpMessage::set_basic(uint8_t method, uint16_t status, int64_t content_length, bool keep_alive) void SrsHttpMessage::set_basic(uint8_t method, uint16_t status, int64_t content_length)
{ {
_method = method; _method = method;
_status = status; _status = status;
_content_length = content_length; _content_length = content_length;
}
void SrsHttpMessage::set_header(SrsHttpHeader* header, bool keep_alive)
{
_header = *header;
_keep_alive = keep_alive; _keep_alive = keep_alive;
// whether chunked.
chunked = (header->get("Transfer-Encoding") == "chunked");
} }
srs_error_t SrsHttpMessage::update(string url, bool allow_jsonp, vector<SrsHttpHeaderField>& headers) srs_error_t SrsHttpMessage::set_url(string url, bool allow_jsonp)
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
_url = url; _url = url;
_headers = headers;
// use server public ip when host not specified.
// whether chunked.
std::string transfer_encoding = get_request_header("Transfer-Encoding");
chunked = (transfer_encoding == "chunked");
// parse uri from url.
std::string host = get_request_header("Host");
// use server public ip when no host specified.
// to make telnet happy. // to make telnet happy.
std::string host = _header.get("Host");
if (host.empty()) { if (host.empty()) {
host= srs_get_public_internet_address(); host= srs_get_public_internet_address();
} }
// parse uri to schema/server:port/path?query // parse uri from schema/server:port/path?query
std::string uri = "http://" + host + _url; std::string uri = _url;
if (!host.empty()) {
uri = "http://" + host + _url;
}
if ((err = _uri->initialize(uri)) != srs_success) { if ((err = _uri->initialize(uri)) != srs_success) {
return srs_error_wrap(err, "init uri"); return srs_error_wrap(err, "init uri %s", uri.c_str());
} }
// parse ext. // parse ext.
@ -546,39 +544,9 @@ string SrsHttpMessage::query_get(string key)
return v; return v;
} }
int SrsHttpMessage::request_header_count() SrsHttpHeader* SrsHttpMessage::header()
{ {
return (int)_headers.size(); return &_header;
}
string SrsHttpMessage::request_header_key_at(int index)
{
srs_assert(index < request_header_count());
SrsHttpHeaderField item = _headers[index];
return item.first;
}
string SrsHttpMessage::request_header_value_at(int index)
{
srs_assert(index < request_header_count());
SrsHttpHeaderField item = _headers[index];
return item.second;
}
string SrsHttpMessage::get_request_header(string name)
{
std::vector<SrsHttpHeaderField>::iterator it;
for (it = _headers.begin(); it != _headers.end(); ++it) {
SrsHttpHeaderField& elem = *it;
std::string key = elem.first;
std::string value = elem.second;
if (key == name) {
return value;
}
}
return "";
} }
SrsRequest* SrsHttpMessage::to_request(string vhost) SrsRequest* SrsHttpMessage::to_request(string vhost)
@ -598,7 +566,7 @@ SrsRequest* SrsHttpMessage::to_request(string vhost)
// generate others. // generate others.
req->tcUrl = "rtmp://" + vhost + "/" + req->app; req->tcUrl = "rtmp://" + vhost + "/" + req->app;
req->pageUrl = get_request_header("Referer"); req->pageUrl = _header.get("Referer");
req->objectEncoding = 0; req->objectEncoding = 0;
std::string query = _uri->get_query(); std::string query = _uri->get_query();
@ -863,7 +831,7 @@ srs_error_t SrsHttpResponseWriter::send_header(char* data, int size)
return srs_error_wrap(err, "filter header"); return srs_error_wrap(err, "filter header");
} }
// write headers // write header
hdr->write(ss); hdr->write(ss);
// header_eof // header_eof

@ -37,9 +37,6 @@ class ISrsReader;
class SrsHttpResponseReader; class SrsHttpResponseReader;
class ISrsProtocolReadWriter; class ISrsProtocolReadWriter;
// For http header.
typedef std::pair<std::string, std::string> SrsHttpHeaderField;
// A wrapper for http-parser, // A wrapper for http-parser,
// provides HTTP message originted service. // provides HTTP message originted service.
class SrsHttpParser class SrsHttpParser
@ -57,9 +54,9 @@ private:
std::string field_name; std::string field_name;
std::string field_value; std::string field_value;
SrsHttpParseState state; SrsHttpParseState state;
http_parser header; http_parser hp_header;
std::string url; std::string url;
std::vector<SrsHttpHeaderField> headers; SrsHttpHeader* header;
const char* pbody; const char* pbody;
public: public:
SrsHttpParser(); SrsHttpParser();
@ -88,9 +85,6 @@ private:
static int on_body(http_parser* parser, const char* at, size_t length); static int on_body(http_parser* parser, const char* at, size_t length);
}; };
// for http header.
typedef std::pair<std::string, std::string> SrsHttpHeaderField;
// A Request represents an HTTP request received by a server // A Request represents an HTTP request received by a server
// or to be sent by a client. // or to be sent by a client.
// //
@ -100,34 +94,36 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField;
class SrsHttpMessage : public ISrsHttpMessage class SrsHttpMessage : public ISrsHttpMessage
{ {
private: private:
// The parsed url.
std::string _url;
// The extension of file, for example, .flv
std::string _ext;
// The body object, reader object. // The body object, reader object.
// @remark, user can get body in string by get_body(). // @remark, user can get body in string by get_body().
SrsHttpResponseReader* _body; SrsHttpResponseReader* _body;
// Whether the body is chunked.
bool chunked;
// Whether the body is infinite chunked. // Whether the body is infinite chunked.
bool infinite_chunked; bool infinite_chunked;
// The uri parser
SrsHttpUri* _uri;
// Use a buffer to read and send ts file. // Use a buffer to read and send ts file.
// TODO: FIXME: remove it. // TODO: FIXME: remove it.
char* _http_ts_send_buffer; char* _http_ts_send_buffer;
// The http headers
std::vector<SrsHttpHeaderField> _headers;
// The query map
std::map<std::string, std::string> _query;
// The transport connection, can be NULL. // The transport connection, can be NULL.
SrsConnection* owner_conn; SrsConnection* owner_conn;
private: private:
uint8_t _method; uint8_t _method;
uint16_t _status; uint16_t _status;
int64_t _content_length; int64_t _content_length;
private:
// The http headers
SrsHttpHeader _header;
// Whether the request indicates should keep alive for the http connection. // Whether the request indicates should keep alive for the http connection.
bool _keep_alive; bool _keep_alive;
// Whether the body is chunked.
bool chunked;
private:
// The parsed url.
std::string _url;
// The extension of file, for example, .flv
std::string _ext;
// The uri parser
SrsHttpUri* _uri;
// The query map
std::map<std::string, std::string> _query;
private: private:
// Whether request is jsonp. // Whether request is jsonp.
bool jsonp; bool jsonp;
@ -138,9 +134,11 @@ public:
virtual ~SrsHttpMessage(); virtual ~SrsHttpMessage();
public: public:
// Set the basic information for HTTP request. // Set the basic information for HTTP request.
virtual void set_basic(uint8_t method, uint16_t status, int64_t content_length, bool keep_alive); virtual void set_basic(uint8_t method, uint16_t status, int64_t content_length);
// Set HTTP header and whether the request require keep alive.
virtual void set_header(SrsHttpHeader* header, bool keep_alive);
// set the original messages, then update the message. // set the original messages, then update the message.
virtual srs_error_t update(std::string url, bool allow_jsonp, std::vector<SrsHttpHeaderField>& headers); virtual srs_error_t set_url(std::string url, bool allow_jsonp);
public: public:
// Get the owner connection, maybe NULL. // Get the owner connection, maybe NULL.
virtual SrsConnection* connection(); virtual SrsConnection* connection();
@ -187,10 +185,7 @@ public:
// then query_get("start") is "100", and query_get("end") is "200" // then query_get("start") is "100", and query_get("end") is "200"
virtual std::string query_get(std::string key); virtual std::string query_get(std::string key);
// Get the headers. // Get the headers.
virtual int request_header_count(); virtual SrsHttpHeader* header();
virtual std::string request_header_key_at(int index);
virtual std::string request_header_value_at(int index);
virtual std::string get_request_header(std::string name);
public: public:
// Convert the http message to a request. // Convert the http message to a request.
// @remark user must free the return request. // @remark user must free the return request.

@ -134,6 +134,7 @@ VOID TEST(ProtocolHTTPTest, HTTPHeader)
SrsHttpHeader h; SrsHttpHeader h;
h.set("Server", "SRS"); h.set("Server", "SRS");
EXPECT_STREQ("SRS", h.get("Server").c_str()); EXPECT_STREQ("SRS", h.get("Server").c_str());
EXPECT_EQ(1, h.count());
stringstream ss; stringstream ss;
h.write(ss); h.write(ss);
@ -141,17 +142,20 @@ VOID TEST(ProtocolHTTPTest, HTTPHeader)
h.del("Server"); h.del("Server");
EXPECT_TRUE(h.get("Server").empty()); EXPECT_TRUE(h.get("Server").empty());
EXPECT_EQ(0, h.count());
EXPECT_EQ(-1, h.content_length()); EXPECT_EQ(-1, h.content_length());
h.set_content_length(0); h.set_content_length(0);
EXPECT_EQ(0, h.content_length()); EXPECT_EQ(0, h.content_length());
EXPECT_EQ(1, h.count());
h.set_content_length(1024); h.set_content_length(1024);
EXPECT_EQ(1024, h.content_length()); EXPECT_EQ(1024, h.content_length());
h.set_content_type("text/plain"); h.set_content_type("text/plain");
EXPECT_STREQ("text/plain", h.content_type().c_str()); EXPECT_STREQ("text/plain", h.content_type().c_str());
EXPECT_EQ(2, h.count());
} }
VOID TEST(ProtocolHTTPTest, HTTPCommonHandler) VOID TEST(ProtocolHTTPTest, HTTPCommonHandler)

Loading…
Cancel
Save