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
SrsJsonObject* headers = SrsJsonAny::object();
data->set("headers", 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()));
}
r->header()->dumps(headers);
// server informations
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()
{
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 (enabled) {
for (int i = 0; i < r->request_header_count(); i++) {
string k = r->request_header_key_at(i);
if (k == "Origin" || k == "origin") {
required = true;
break;
}
}
SrsHttpHeader* h = r->header();
required = !h->get("Origin").empty();
}
// When CORS required, set the CORS headers.

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

@ -39,11 +39,13 @@ using namespace std;
SrsHttpParser::SrsHttpParser()
{
buffer = new SrsFastStream();
header = NULL;
}
SrsHttpParser::~SrsHttpParser()
{
srs_freep(buffer);
srs_freep(header);
}
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)
{
*ppmsg = NULL;
srs_error_t err = srs_success;
*ppmsg = NULL;
// reset request data.
field_name = "";
field_value = "";
expect_field_name = true;
// Reset request data.
state = SrsHttpParseStateInit;
header = http_parser();
hp_header = http_parser();
// Reset the message url.
url = "";
headers.clear();
// The body that we have read from cache.
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
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);
// 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, headers)) != srs_success) {
msg->set_basic(hp_header.method, hp_header.status_code, hp_header.content_length);
msg->set_header(header, http_should_keep_alive(&hp_header));
if ((err = msg->set_url(url, jsonp)) != srs_success) {
srs_freep(msg);
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;
}
@ -167,7 +165,7 @@ int SrsHttpParser::on_headers_complete(http_parser* parser)
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj);
obj->header = *parser;
obj->hp_header = *parser;
// save the parser when header parse completed.
obj->state = SrsHttpParseStateHeaderComplete;
@ -196,7 +194,7 @@ int SrsHttpParser::on_url(http_parser* parser, const char* at, size_t length)
srs_assert(obj);
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);
@ -211,16 +209,12 @@ int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t l
// field value=>name, reap the field.
if (!obj->expect_field_name) {
obj->headers.push_back(std::make_pair(obj->field_name, obj->field_value));
// reset the field name when parsed.
obj->field_name = "";
obj->field_value = "";
obj->header->set(obj->field_name, obj->field_value);
}
obj->expect_field_name = true;
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);
@ -233,7 +227,7 @@ int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t l
srs_assert(obj);
if (length > 0) {
obj->field_value.append(at, (int)length);
obj->field_value = string(at, (int)length);
}
obj->expect_field_name = false;
@ -281,38 +275,42 @@ SrsHttpMessage::~SrsHttpMessage()
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;
_status = status;
_content_length = content_length;
}
void SrsHttpMessage::set_header(SrsHttpHeader* header, bool keep_alive)
{
_header = *header;
_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;
_url = url;
_headers = headers;
// 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.
// use server public ip when host not specified.
// to make telnet happy.
std::string host = _header.get("Host");
if (host.empty()) {
host= srs_get_public_internet_address();
}
// parse uri to schema/server:port/path?query
std::string uri = "http://" + host + _url;
// parse uri from schema/server:port/path?query
std::string uri = _url;
if (!host.empty()) {
uri = "http://" + host + _url;
}
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.
@ -546,39 +544,9 @@ string SrsHttpMessage::query_get(string key)
return v;
}
int SrsHttpMessage::request_header_count()
SrsHttpHeader* SrsHttpMessage::header()
{
return (int)_headers.size();
}
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 "";
return &_header;
}
SrsRequest* SrsHttpMessage::to_request(string vhost)
@ -598,7 +566,7 @@ SrsRequest* SrsHttpMessage::to_request(string vhost)
// generate others.
req->tcUrl = "rtmp://" + vhost + "/" + req->app;
req->pageUrl = get_request_header("Referer");
req->pageUrl = _header.get("Referer");
req->objectEncoding = 0;
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");
}
// write headers
// write header
hdr->write(ss);
// header_eof

@ -37,9 +37,6 @@ class ISrsReader;
class SrsHttpResponseReader;
class ISrsProtocolReadWriter;
// For http header.
typedef std::pair<std::string, std::string> SrsHttpHeaderField;
// A wrapper for http-parser,
// provides HTTP message originted service.
class SrsHttpParser
@ -57,9 +54,9 @@ private:
std::string field_name;
std::string field_value;
SrsHttpParseState state;
http_parser header;
http_parser hp_header;
std::string url;
std::vector<SrsHttpHeaderField> headers;
SrsHttpHeader* header;
const char* pbody;
public:
SrsHttpParser();
@ -88,9 +85,6 @@ private:
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
// or to be sent by a client.
//
@ -100,34 +94,36 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField;
class SrsHttpMessage : public ISrsHttpMessage
{
private:
// The parsed url.
std::string _url;
// The extension of file, for example, .flv
std::string _ext;
// The body object, reader object.
// @remark, user can get body in string by get_body().
SrsHttpResponseReader* _body;
// Whether the body is chunked.
bool chunked;
// Whether the body is infinite chunked.
bool infinite_chunked;
// The uri parser
SrsHttpUri* _uri;
// Use a buffer to read and send ts file.
// TODO: FIXME: remove it.
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.
SrsConnection* owner_conn;
private:
uint8_t _method;
uint16_t _status;
int64_t _content_length;
private:
// The http headers
SrsHttpHeader _header;
// Whether the request indicates should keep alive for the http connection.
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:
// Whether request is jsonp.
bool jsonp;
@ -138,9 +134,11 @@ public:
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);
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.
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:
// Get the owner connection, maybe NULL.
virtual SrsConnection* connection();
@ -187,10 +185,7 @@ public:
// then query_get("start") is "100", and query_get("end") is "200"
virtual std::string query_get(std::string key);
// Get the headers.
virtual int request_header_count();
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);
virtual SrsHttpHeader* header();
public:
// Convert the http message to a request.
// @remark user must free the return request.

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

Loading…
Cancel
Save