1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

refine the http request reader.

This commit is contained in:
winlin 2015-03-04 18:20:15 +08:00
parent 3e394a5f06
commit 025b707330
6 changed files with 289 additions and 133 deletions

View file

@ -43,6 +43,7 @@ using namespace std;
#define SRS_DEFAULT_HTTP_PORT 80
#define SRS_HTTP_HEADER_BUFFER 1024
#define SRS_HTTP_BODY_BUFFER 1024
// for http parser macros
#define SRS_CONSTS_HTTP_OPTIONS HTTP_OPTIONS
@ -227,6 +228,22 @@ ISrsHttpResponseWriter::~ISrsHttpResponseWriter()
{
}
ISrsHttpResponseReader::ISrsHttpResponseReader()
{
}
ISrsHttpResponseReader::~ISrsHttpResponseReader()
{
}
ISrsHttpResponseAppender::ISrsHttpResponseAppender()
{
}
ISrsHttpResponseAppender::~ISrsHttpResponseAppender()
{
}
ISrsHttpHandler::ISrsHttpHandler()
{
entry = NULL;
@ -833,11 +850,63 @@ int SrsHttpResponseWriter::send_header(char* data, int size)
return skt->write((void*)buf.c_str(), buf.length(), NULL);
}
SrsHttpMessage::SrsHttpMessage()
SrsHttpResponseReader::SrsHttpResponseReader(SrsHttpMessage* msg, SrsStSocket* io)
{
skt = io;
owner = msg;
cache = new SrsSimpleBuffer();
}
SrsHttpResponseReader::~SrsHttpResponseReader()
{
srs_freep(cache);
}
int SrsHttpResponseReader::read(int max, std::string& data)
{
int ret = ERROR_SUCCESS;
// read from cache first.
if (cache->length() > 0) {
int nb_bytes = srs_min(cache->length(), max);
data.append(cache->bytes(), nb_bytes);
cache->erase(nb_bytes);
return ret;
}
// read some from underlayer.
int left = srs_max(SRS_HTTP_BODY_BUFFER, max);
// read from io.
char* buf = new char[left];
SrsAutoFree(char, buf);
ssize_t nread = 0;
if ((ret = skt->read(buf, left, &nread)) != ERROR_SUCCESS) {
return ret;
}
if (nread) {
data.append(buf, nread);
}
return ret;
}
int SrsHttpResponseReader::append(char* data, int size)
{
int ret = ERROR_SUCCESS;
cache->append(data, size);
return ret;
}
SrsHttpMessage::SrsHttpMessage(SrsStSocket* io)
{
_body = new SrsSimpleBuffer();
_state = SrsHttpParseStateInit;
_uri = new SrsHttpUri();
_body = new SrsHttpResponseReader(this, io);
_http_ts_send_buffer = new char[__SRS_HTTP_TS_SEND_BUFFER_SIZE];
}
@ -898,18 +967,6 @@ char* SrsHttpMessage::http_ts_send_buffer()
return _http_ts_send_buffer;
}
void SrsHttpMessage::reset()
{
_state = SrsHttpParseStateInit;
_body->erase(_body->length());
_url = "";
}
bool SrsHttpMessage::is_complete()
{
return _state == SrsHttpParseStateComplete;
}
u_int8_t SrsHttpMessage::method()
{
return (u_int8_t)_header.method;
@ -993,25 +1050,49 @@ string SrsHttpMessage::path()
return _uri->get_path();
}
string SrsHttpMessage::body()
void SrsHttpMessage::set(string url, http_parser* header, string body, vector<SrsHttpHeaderField>& headers)
{
std::string b;
_url = url;
_header = *header;
_headers = headers;
if (!body.empty()) {
_body->append((char*)body.data(), (int)body.length());
}
}
int SrsHttpMessage::body_read_all(string body)
{
int ret = ERROR_SUCCESS;
if (_body && _body->length() > 0) {
b.append(_body->bytes(), _body->length());
// when content length specified, read specified length.
if ((int64_t)_header.content_length > 0) {
int left = (int)(int64_t)_header.content_length;
while (left > 0) {
int nb_read = (int)body.length();
if ((ret = _body->read(left, body)) != ERROR_SUCCESS) {
return ret;
}
left -= (int)body.length() - nb_read;
}
return ret;
}
return b;
}
char* SrsHttpMessage::body_raw()
{
return _body? _body->bytes() : NULL;
}
int64_t SrsHttpMessage::body_size()
{
return (int64_t)_body->length();
// chunked encoding, read util got size=0 chunk.
for (;;) {
int nb_read = (int)body.length();
if ((ret = _body->read(0, body)) != ERROR_SUCCESS) {
return ret;
}
// eof.
if (nb_read == (int)body.length()) {
break;
}
}
return ret;
}
int64_t SrsHttpMessage::content_length()
@ -1019,26 +1100,6 @@ int64_t SrsHttpMessage::content_length()
return _header.content_length;
}
void SrsHttpMessage::set_url(string url)
{
_url = url;
}
void SrsHttpMessage::set_state(SrsHttpParseState state)
{
_state = state;
}
void SrsHttpMessage::set_header(http_parser* header)
{
memcpy(&_header, header, sizeof(http_parser));
}
void SrsHttpMessage::append_body(const char* body, int length)
{
_body->append(body, length);
}
string SrsHttpMessage::query_get(string key)
{
std::string v;
@ -1052,33 +1113,28 @@ string SrsHttpMessage::query_get(string key)
int SrsHttpMessage::request_header_count()
{
return (int)headers.size();
return (int)_headers.size();
}
string SrsHttpMessage::request_header_key_at(int index)
{
srs_assert(index < request_header_count());
SrsHttpHeaderField item = headers[index];
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];
SrsHttpHeaderField item = _headers[index];
return item.second;
}
void SrsHttpMessage::set_request_header(string key, string value)
{
headers.push_back(std::make_pair(key, value));
}
string SrsHttpMessage::get_request_header(string name)
{
std::vector<SrsHttpHeaderField>::iterator it;
for (it = headers.begin(); it != headers.end(); ++it) {
for (it = _headers.begin(); it != _headers.end(); ++it) {
SrsHttpHeaderField& elem = *it;
std::string key = elem.first;
std::string value = elem.second;
@ -1092,12 +1148,10 @@ string SrsHttpMessage::get_request_header(string name)
SrsHttpParser::SrsHttpParser()
{
msg = NULL;
}
SrsHttpParser::~SrsHttpParser()
{
srs_freep(msg);
}
int SrsHttpParser::initialize(enum http_parser_type type)
@ -1125,26 +1179,31 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg)
*ppmsg = NULL;
int ret = ERROR_SUCCESS;
// the msg must be always NULL
srs_assert(msg == NULL);
msg = new SrsHttpMessage();
// reset request data.
filed_name = "";
// reset response header.
msg->reset();
field_value = "";
expect_filed_name = true;
state = SrsHttpParseStateInit;
header = http_parser();
url = "";
headers.clear();
body = "";
// do parse
if ((ret = parse_message_imp(skt)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("parse http msg failed. ret=%d", ret);
}
srs_freep(msg);
return ret;
}
// create msg
SrsHttpMessage* msg = new SrsHttpMessage(skt);
// dumps the header and body read.
msg->set(url, &header, body, headers);
// initalize http msg, parse url.
if ((ret = msg->initialize()) != ERROR_SUCCESS) {
srs_error("initialize http msg failed. ret=%d", ret);
@ -1154,7 +1213,6 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg)
// parse ok, return the msg.
*ppmsg = msg;
msg = NULL;
return ret;
}
@ -1163,13 +1221,14 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt)
{
int ret = ERROR_SUCCESS;
// the msg should never be NULL
srs_assert(msg != NULL);
ssize_t nread = 0;
ssize_t nparsed = 0;
char* buf = new char[SRS_HTTP_HEADER_BUFFER];
SrsAutoFree(char, buf);
// parser header.
char buf[SRS_HTTP_HEADER_BUFFER];
for (;;) {
ssize_t nread;
if ((ret = skt->read(buf, (size_t)sizeof(buf), &nread)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("read body from server failed. ret=%d", ret);
@ -1177,20 +1236,28 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt)
return ret;
}
ssize_t nparsed = http_parser_execute(&parser, &settings, buf, nread);
nparsed = http_parser_execute(&parser, &settings, buf, nread);
srs_info("read_size=%d, nparsed=%d", (int)nread, (int)nparsed);
// check header size.
if (msg->is_complete()) {
return ret;
// ok atleast header completed,
// never wait for body completed, for maybe chunked.
if (state == SrsHttpParseStateHeaderComplete || state == SrsHttpParseStateMessageComplete) {
break;
}
// when not complete, the parser should consume all bytes.
if (nparsed != nread) {
ret = ERROR_HTTP_PARSE_HEADER;
srs_error("parse response error, parsed(%d)!=read(%d), ret=%d", (int)nparsed, (int)nread, ret);
return ret;
}
}
// when parse completed, cache the left body.
if (nread && nparsed < nread) {
body.append(buf + nparsed, nread - nparsed);
srs_info("cache %d bytes read body.", nread - nparsed);
}
return ret;
}
@ -1198,7 +1265,9 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt)
int SrsHttpParser::on_message_begin(http_parser* parser)
{
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
obj->msg->set_state(SrsHttpParseStateStart);
srs_assert(obj);
obj->state = SrsHttpParseStateStart;
srs_info("***MESSAGE BEGIN***");
@ -1208,7 +1277,11 @@ int SrsHttpParser::on_message_begin(http_parser* parser)
int SrsHttpParser::on_headers_complete(http_parser* parser)
{
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
obj->msg->set_header(parser);
srs_assert(obj);
obj->header = *parser;
// save the parser when header parse completed.
obj->state = SrsHttpParseStateHeaderComplete;
srs_info("***HEADERS COMPLETE***");
@ -1219,8 +1292,10 @@ int SrsHttpParser::on_headers_complete(http_parser* parser)
int SrsHttpParser::on_message_complete(http_parser* parser)
{
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
// save the parser when header parse completed.
obj->msg->set_state(SrsHttpParseStateComplete);
srs_assert(obj);
// save the parser when body parse completed.
obj->state = SrsHttpParseStateMessageComplete;
srs_info("***MESSAGE COMPLETE***\n");
@ -1230,13 +1305,10 @@ int SrsHttpParser::on_message_complete(http_parser* parser)
int SrsHttpParser::on_url(http_parser* parser, const char* at, size_t length)
{
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj);
if (length > 0) {
std::string url;
url.append(at, (int)length);
obj->msg->set_url(url);
obj->url.append(at, (int)length);
}
srs_info("Method: %d, Url: %.*s", parser->method, (int)length, at);
@ -1247,44 +1319,47 @@ int SrsHttpParser::on_url(http_parser* parser, const char* at, size_t length)
int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t length)
{
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj);
// field value=>name, reap the field.
if (!obj->expect_filed_name) {
obj->headers.push_back(std::make_pair(obj->filed_name, obj->field_value));
// reset the field name when value parsed.
obj->filed_name = "";
obj->field_value = "";
}
obj->expect_filed_name = true;
if (length > 0) {
srs_assert(obj);
obj->filed_name.append(at, (int)length);
}
srs_info("Header field: %.*s", (int)length, at);
srs_trace("Header field: %.*s", (int)length, at);
return 0;
}
int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t length)
{
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj);
if (length > 0) {
srs_assert(obj);
srs_assert(obj->msg);
std::string field_value;
field_value.append(at, (int)length);
obj->msg->set_request_header(obj->filed_name, field_value);
obj->filed_name = "";
obj->field_value.append(at, (int)length);
}
obj->expect_filed_name = false;
srs_info("Header value: %.*s", (int)length, at);
srs_trace("Header value: %.*s", (int)length, at);
return 0;
}
int SrsHttpParser::on_body(http_parser* parser, const char* at, size_t length)
{
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj);
if (length > 0) {
srs_assert(obj);
srs_assert(obj->msg);
obj->msg->append_body(at, (int)length);
obj->body.append(at, (int)length);
}
srs_info("Body: %.*s", (int)length, at);