Use http-parser 2.9.2

pull/1651/head
winlin 6 years ago
parent 646d490a18
commit cfc92d5e93

File diff suppressed because it is too large Load Diff

@ -544,8 +544,8 @@ private:
#endif
// The http-parser is license under MIT at https://github.com/nodejs/http-parser/blob/master/LICENSE-MIT
// Version: 2.1 from https://github.com/nodejs/http-parser/releases/tag/v2.1
// File: https://github.com/nodejs/http-parser/blob/80819384450b5511a3d1c424dd92a5843c891364/http_parser.h
// Version: 2.9.2 from https://github.com/nodejs/http-parser/releases/tag/v2.9.2
// File: https://raw.githubusercontent.com/nodejs/http-parser/5c17dad400e45c5a442a63f250fff2638d144682/http_parser.h
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
@ -598,13 +598,15 @@ private:
extern "C" {
#endif
/* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 1
#define HTTP_PARSER_VERSION_MINOR 9
#define HTTP_PARSER_VERSION_PATCH 2
#include <sys/types.h>
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
#include <BaseTsd.h>
#include <stddef.h>
#if defined(_WIN32) && !defined(__MINGW32__) && \
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
#include <BaseTsd.h>
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
@ -624,9 +626,16 @@ typedef unsigned __int64 uint64_t;
# define HTTP_PARSER_STRICT 1
#endif
/* Maximium header size allowed */
#define HTTP_MAX_HEADER_SIZE (80*1024)
/* Maximium header size allowed. If the macro is not defined
* before including this header then the default is used. To
* change the maximum header size, define the macro in the build
* environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
* the effective limit on the size of the header, define the macro
* to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
*/
#ifndef HTTP_MAX_HEADER_SIZE
# define HTTP_MAX_HEADER_SIZE (80*1024)
#endif
typedef struct http_parser http_parser;
typedef struct http_parser_settings http_parser_settings;
@ -641,7 +650,12 @@ typedef struct http_parser_settings http_parser_settings;
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
* chunked' headers that indicate the presence of a body.
*
* http_data_cb does not return data chunks. It will be call arbitrarally
* Returning `2` from on_headers_complete will tell parser that it should not
* expect neither a body nor any futher responses on this connection. This is
* useful for handling responses to a CONNECT request which may not contain
* `Upgrade` or `Connection: upgrade` headers.
*
* http_data_cb does not return data chunks. It will be called arbitrarily
* many times for each string. E.G. you might get 10 callbacks for "on_url"
* each providing just a few characters more data.
*/
@ -649,6 +663,76 @@ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
typedef int (*http_cb) (http_parser*);
/* Status Codes */
#define HTTP_STATUS_MAP(XX) \
XX(100, CONTINUE, Continue) \
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
XX(102, PROCESSING, Processing) \
XX(200, OK, OK) \
XX(201, CREATED, Created) \
XX(202, ACCEPTED, Accepted) \
XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
XX(204, NO_CONTENT, No Content) \
XX(205, RESET_CONTENT, Reset Content) \
XX(206, PARTIAL_CONTENT, Partial Content) \
XX(207, MULTI_STATUS, Multi-Status) \
XX(208, ALREADY_REPORTED, Already Reported) \
XX(226, IM_USED, IM Used) \
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
XX(302, FOUND, Found) \
XX(303, SEE_OTHER, See Other) \
XX(304, NOT_MODIFIED, Not Modified) \
XX(305, USE_PROXY, Use Proxy) \
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
XX(400, BAD_REQUEST, Bad Request) \
XX(401, UNAUTHORIZED, Unauthorized) \
XX(402, PAYMENT_REQUIRED, Payment Required) \
XX(403, FORBIDDEN, Forbidden) \
XX(404, NOT_FOUND, Not Found) \
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
XX(408, REQUEST_TIMEOUT, Request Timeout) \
XX(409, CONFLICT, Conflict) \
XX(410, GONE, Gone) \
XX(411, LENGTH_REQUIRED, Length Required) \
XX(412, PRECONDITION_FAILED, Precondition Failed) \
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
XX(414, URI_TOO_LONG, URI Too Long) \
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
XX(417, EXPECTATION_FAILED, Expectation Failed) \
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
XX(423, LOCKED, Locked) \
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
XX(501, NOT_IMPLEMENTED, Not Implemented) \
XX(502, BAD_GATEWAY, Bad Gateway) \
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
XX(508, LOOP_DETECTED, Loop Detected) \
XX(510, NOT_EXTENDED, Not Extended) \
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
enum http_status
{
#define XX(num, name, string) HTTP_STATUS_##name = num,
HTTP_STATUS_MAP(XX)
#undef XX
};
/* Request Methods */
#define HTTP_METHOD_MAP(XX) \
XX(0, DELETE, DELETE) \
@ -660,7 +744,7 @@ typedef int (*http_cb) (http_parser*);
XX(5, CONNECT, CONNECT) \
XX(6, OPTIONS, OPTIONS) \
XX(7, TRACE, TRACE) \
/* webdav */ \
/* WebDAV */ \
XX(8, COPY, COPY) \
XX(9, LOCK, LOCK) \
XX(10, MKCOL, MKCOL) \
@ -669,19 +753,30 @@ typedef int (*http_cb) (http_parser*);
XX(13, PROPPATCH, PROPPATCH) \
XX(14, SEARCH, SEARCH) \
XX(15, UNLOCK, UNLOCK) \
XX(16, BIND, BIND) \
XX(17, REBIND, REBIND) \
XX(18, UNBIND, UNBIND) \
XX(19, ACL, ACL) \
/* subversion */ \
XX(16, REPORT, REPORT) \
XX(17, MKACTIVITY, MKACTIVITY) \
XX(18, CHECKOUT, CHECKOUT) \
XX(19, MERGE, MERGE) \
XX(20, REPORT, REPORT) \
XX(21, MKACTIVITY, MKACTIVITY) \
XX(22, CHECKOUT, CHECKOUT) \
XX(23, MERGE, MERGE) \
/* upnp */ \
XX(20, MSEARCH, M-SEARCH) \
XX(21, NOTIFY, NOTIFY) \
XX(22, SUBSCRIBE, SUBSCRIBE) \
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
XX(24, MSEARCH, M-SEARCH) \
XX(25, NOTIFY, NOTIFY) \
XX(26, SUBSCRIBE, SUBSCRIBE) \
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
/* RFC-5789 */ \
XX(24, PATCH, PATCH) \
XX(25, PURGE, PURGE) \
XX(28, PATCH, PATCH) \
XX(29, PURGE, PURGE) \
/* CalDAV */ \
XX(30, MKCALENDAR, MKCALENDAR) \
/* RFC-2068, section 19.6.1.2 */ \
XX(31, LINK, LINK) \
XX(32, UNLINK, UNLINK) \
/* icecast */ \
XX(33, SOURCE, SOURCE) \
enum http_method
{
@ -699,9 +794,11 @@ enum flags
{ F_CHUNKED = 1 << 0
, F_CONNECTION_KEEP_ALIVE = 1 << 1
, F_CONNECTION_CLOSE = 1 << 2
, F_TRAILING = 1 << 3
, F_UPGRADE = 1 << 4
, F_SKIPBODY = 1 << 5
, F_CONNECTION_UPGRADE = 1 << 3
, F_TRAILING = 1 << 4
, F_UPGRADE = 1 << 5
, F_SKIPBODY = 1 << 6
, F_CONTENTLENGTH = 1 << 7
};
@ -715,13 +812,15 @@ enum flags
\
/* Callback-related errors */ \
XX(CB_message_begin, "the on_message_begin callback failed") \
XX(CB_status_complete, "the on_status_complete callback failed") \
XX(CB_url, "the on_url callback failed") \
XX(CB_header_field, "the on_header_field callback failed") \
XX(CB_header_value, "the on_header_value callback failed") \
XX(CB_headers_complete, "the on_headers_complete callback failed") \
XX(CB_body, "the on_body callback failed") \
XX(CB_message_complete, "the on_message_complete callback failed") \
XX(CB_status, "the on_status callback failed") \
XX(CB_chunk_header, "the on_chunk_header callback failed") \
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
\
/* Parsing-related errors */ \
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
@ -742,6 +841,8 @@ enum flags
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
XX(INVALID_CONTENT_LENGTH, \
"invalid character in content-length header") \
XX(UNEXPECTED_CONTENT_LENGTH, \
"unexpected content-length header") \
XX(INVALID_CHUNK_SIZE, \
"invalid character in chunk size header") \
XX(INVALID_CONSTANT, "invalid constant string") \
@ -765,11 +866,12 @@ enum http_errno {
struct http_parser {
/** PRIVATE **/
unsigned char type : 2; /* enum http_parser_type */
unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */
unsigned char state; /* enum state from http_parser.c */
unsigned char header_state; /* enum header_state from http_parser.c */
unsigned char index; /* index into current matcher */
unsigned int type : 2; /* enum http_parser_type */
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
unsigned int state : 7; /* enum state from http_parser.c */
unsigned int header_state : 7; /* enum header_state from http_parser.c */
unsigned int index : 7; /* index into current matcher */
unsigned int lenient_http_headers : 1;
uint32_t nread; /* # bytes read in various scenarios */
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
@ -777,16 +879,16 @@ struct http_parser {
/** READ-ONLY **/
unsigned short http_major;
unsigned short http_minor;
unsigned short status_code; /* responses only */
unsigned char method; /* requests only */
unsigned char http_errno : 7;
unsigned int status_code : 16; /* responses only */
unsigned int method : 8; /* requests only */
unsigned int http_errno : 7;
/* 1 = Upgrade header was present and the parser has exited because of that.
* 0 = No upgrade header present.
* Should be checked when http_parser_execute() returns in addition to
* error checking.
*/
unsigned char upgrade : 1;
unsigned int upgrade : 1;
/** PUBLIC **/
void *data; /* A pointer to get hook to the "connection" or "socket" object */
@ -796,12 +898,17 @@ struct http_parser {
struct http_parser_settings {
http_cb on_message_begin;
http_data_cb on_url;
http_cb on_status_complete;
http_data_cb on_status;
http_data_cb on_header_field;
http_data_cb on_header_value;
http_cb on_headers_complete;
http_data_cb on_body;
http_cb on_message_complete;
/* When on_chunk_header is called, the current chunk length is stored
* in parser->content_length.
*/
http_cb on_chunk_header;
http_cb on_chunk_complete;
};
@ -835,9 +942,28 @@ struct http_parser_url {
};
/* Returns the library version. Bits 16-23 contain the major version number,
* bits 8-15 the minor version number and bits 0-7 the patch level.
* Usage example:
*
* unsigned long version = http_parser_version();
* unsigned major = (version >> 16) & 255;
* unsigned minor = (version >> 8) & 255;
* unsigned patch = version & 255;
* printf("http_parser v%u.%u.%u\n", major, minor, patch);
*/
unsigned long http_parser_version(void);
void http_parser_init(http_parser *parser, enum http_parser_type type);
/* Initialize http_parser_settings members to 0
*/
void http_parser_settings_init(http_parser_settings *settings);
/* Executes the parser. Returns number of parsed bytes. Sets
* `parser->http_errno` on error. */
size_t http_parser_execute(http_parser *parser,
const http_parser_settings *settings,
const char *data,
@ -855,12 +981,18 @@ int http_should_keep_alive(const http_parser *parser);
/* Returns a string version of the HTTP method. */
const char *http_method_str(enum http_method m);
/* Returns a string version of the HTTP status code. */
const char *http_status_str(enum http_status s);
/* Return a string name of the given error */
const char *http_errno_name(enum http_errno err);
/* Return a string description of the given error */
const char *http_errno_description(enum http_errno err);
/* Initialize all http_parser_url members to 0 */
void http_parser_url_init(struct http_parser_url *u);
/* Parse a URL; return nonzero on failure */
int http_parser_parse_url(const char *buf, size_t buflen,
int is_connect,
@ -872,6 +1004,9 @@ void http_parser_pause(http_parser *parser, int paused);
/* Checks if this is the final chunk of the body. */
int http_body_is_final(const http_parser *parser);
/* Change the maximum header size provided at compile time. */
void http_parser_set_max_header_size(uint32_t size);
#ifdef __cplusplus
}
#endif

@ -249,6 +249,12 @@ int SrsHttpParser::on_body(http_parser* parser, const char* at, size_t length)
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj);
// When got body, but no header-parsed, we update it manually.
char* p = obj->buffer->bytes();
if (!obj->header_parsed && p < at) {
obj->header_parsed = int(at - p);
}
srs_info("Body: %.*s", (int)length, at);
return 0;

@ -69,7 +69,7 @@ public:
* one parser can only parse request or response messages.
* @param allow_jsonp whether allow jsonp parser, which indicates the method in query string.
*/
virtual srs_error_t initialize(enum http_parser_type type, bool allow_jsonp);
virtual srs_error_t initialize(enum http_parser_type type, bool allow_jsonp = false);
/**
* always parse a http message,
* that is, the *ppmsg always NOT-NULL when return success.

@ -5597,35 +5597,304 @@ VOID TEST(ProtocolRTMPTest, RTMPHandshakeBytes)
EXPECT_TRUE(bytes.s0s1s2 != NULL);
}
struct MockStage
{
http_parser parser;
const char* at;
size_t length;
MockStage(http_parser* from);
};
MockStage::MockStage(http_parser* from)
{
parser = *from;
at = NULL;
length = 0;
}
class MockParser
{
private:
http_parser_settings settings;
http_parser* parser;
public:
MockStage* message_begin;
MockStage* url;
MockStage* status;
MockStage* header_field;
MockStage* header_value;
MockStage* headers_complete;
MockStage* body;
MockStage* message_complete;
MockStage* chunk_header;
MockStage* chunk_complete;
public:
MockParser();
virtual ~MockParser();
public:
srs_error_t parse(string data);
private:
static int on_message_begin(http_parser* parser);
static int on_url(http_parser* parser, const char* at, size_t length);
static int on_status(http_parser* parser, const char* at, size_t length);
static int on_header_field(http_parser* parser, const char* at, size_t length);
static int on_header_value(http_parser* parser, const char* at, size_t length);
static int on_headers_complete(http_parser* parser);
static int on_body(http_parser* parser, const char* at, size_t length);
static int on_message_complete(http_parser* parser);
static int on_chunk_header(http_parser* parser);
static int on_chunk_complete(http_parser* parser);
};
MockParser::MockParser()
{
parser = new http_parser();
http_parser_init(parser, HTTP_REQUEST);
parser->data = (void*)this;
memset(&settings, 0, sizeof(settings));
settings.on_message_begin = on_message_begin;
settings.on_url = on_url;
settings.on_status = on_status;
settings.on_header_field = on_header_field;
settings.on_header_value = on_header_value;
settings.on_headers_complete = on_headers_complete;
settings.on_body = on_body;
settings.on_message_complete = on_message_complete;
settings.on_chunk_header = on_chunk_header;
settings.on_chunk_complete = on_chunk_complete;
message_begin = NULL;
url = NULL;
status = NULL;
header_field = NULL;
header_value = NULL;
headers_complete = NULL;
body = NULL;
message_complete = NULL;
chunk_header = NULL;
chunk_complete = NULL;
}
MockParser::~MockParser()
{
srs_freep(parser);
srs_freep(message_begin);
srs_freep(url);
srs_freep(status);
srs_freep(header_field);
srs_freep(header_value);
srs_freep(headers_complete);
srs_freep(body);
srs_freep(message_complete);
srs_freep(chunk_header);
srs_freep(chunk_complete);
}
srs_error_t MockParser::parse(string data)
{
srs_error_t err = srs_success;
const char* buf = (const char*)data.data();
size_t size = (size_t)data.length();
size_t nparsed = http_parser_execute(parser, &settings, buf, size);
if (nparsed != size) {
return srs_error_new(-1, "nparsed=%d, size=%d", nparsed, size);
}
return err;
}
int MockParser::on_message_begin(http_parser* parser)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->message_begin);
obj->message_begin = new MockStage(parser);
return 0;
}
int MockParser::on_url(http_parser* parser, const char* at, size_t length)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->url);
obj->url = new MockStage(parser);
obj->url->at = at;
obj->url->length = length;
return 0;
}
int MockParser::on_status(http_parser* parser, const char* at, size_t length)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->status);
obj->status = new MockStage(parser);
obj->status->at = at;
obj->status->length = length;
return 0;
}
int MockParser::on_header_field(http_parser* parser, const char* at, size_t length)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->header_field);
obj->header_field = new MockStage(parser);
obj->header_field->at = at;
obj->header_field->length = length;
return 0;
}
int MockParser::on_header_value(http_parser* parser, const char* at, size_t length)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->header_value);
obj->header_value = new MockStage(parser);
obj->header_value->at = at;
obj->header_value->length = length;
return 0;
}
int MockParser::on_headers_complete(http_parser* parser)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->headers_complete);
obj->headers_complete = new MockStage(parser);
return 0;
}
int MockParser::on_body(http_parser* parser, const char* at, size_t length)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->body);
obj->body = new MockStage(parser);
obj->body->at = at;
obj->body->length = length;
return 0;
}
int MockParser::on_message_complete(http_parser* parser)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->message_complete);
obj->message_complete = new MockStage(parser);
return 0;
}
int MockParser::on_chunk_header(http_parser* parser)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->chunk_header);
obj->chunk_header = new MockStage(parser);
return 0;
}
int MockParser::on_chunk_complete(http_parser* parser)
{
MockParser* obj = (MockParser*)parser->data;
srs_assert(obj);
srs_freep(obj->chunk_complete);
obj->chunk_complete = new MockStage(parser);
return 0;
}
#define HELPER_EXPECT_SUCCESS(x) EXPECT_TRUE(srs_success == (err = x)); srs_freep(err)
#define HELPER_EXPECT_FAILED(x) EXPECT_TRUE(srs_success != (err = x)); srs_freep(err)
VOID TEST(ProtocolHTTPTest, HTTPParser)
{
srs_error_t err;
if (true) {
MockParser parser;
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
HELPER_EXPECT_FAILED(parser.parse(""));
}
if (true) {
MockParser parser;
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
HELPER_EXPECT_FAILED(parser.parse("X"));
}
if (true) {
MockParser parser;
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
HELPER_EXPECT_SUCCESS(parser.parse("T"));
}
if (true) {
MockParser parser;
HELPER_EXPECT_SUCCESS(parser.parse("GET"));
}
}
VOID TEST(ProtocolHTTPTest, ParseHTTPMessage)
{
if (true) {
MockBufferIO bio;
SrsHttpParser hp;
bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello");
bio.append("GET");
EXPECT_TRUE(0 == hp.initialize(HTTP_REQUEST, false));
if (true) {
ISrsHttpMessage* req = NULL;
SrsAutoFree(ISrsHttpMessage, req);
ASSERT_TRUE(0 == hp.parse_message(&bio, &req));
// Should fail if not completed message.
ISrsHttpMessage* req = NULL;
ASSERT_FALSE(0 == hp.parse_message(&bio, &req));
srs_freep(req);
}
if (true) {
MockBufferIO bio;
SrsHttpParser hp;
// We should read body, or next parsing message will fail.
// @see https://github.com/ossrs/srs/issues/1181
EXPECT_FALSE(req->body_reader()->eof());
}
bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello");
EXPECT_TRUE(0 == hp.initialize(HTTP_REQUEST, false));
ISrsHttpMessage* req = NULL;
ASSERT_TRUE(0 == hp.parse_message(&bio, &req));
if (true) {
bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello");
// We should read body, or next parsing message will fail.
// @see https://github.com/ossrs/srs/issues/1181
EXPECT_FALSE(req->body_reader()->eof());
srs_freep(req);
// Should fail because there is body which not read.
// @see https://github.com/ossrs/srs/issues/1181
// Got new packet, notice that previous body still exists in bio.
bio.append("GET /gslb/v2/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello");
ISrsHttpMessage* req = NULL;
SrsAutoFree(ISrsHttpMessage, req);
ASSERT_FALSE(0 == hp.parse_message(&bio, &req));
}
// Should fail because there is body which not read.
// @see https://github.com/ossrs/srs/issues/1181
ASSERT_FALSE(0 == hp.parse_message(&bio, &req));
srs_freep(req);
}
if (true) {

Loading…
Cancel
Save