mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
HTTP: Enable infinite_chunked by default
This commit is contained in:
parent
9e447e541b
commit
a273298e63
5 changed files with 75 additions and 100 deletions
|
@ -1773,9 +1773,8 @@ srs_error_t SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessa
|
||||||
SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(r);
|
SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(r);
|
||||||
srs_assert(hm);
|
srs_assert(hm);
|
||||||
|
|
||||||
srs_trace("HTTP API %s %s, content-length=%" PRId64 ", chunked=%d/%d",
|
srs_trace("HTTP API %s %s, content-length=%" PRId64 ", chunked=%d", r->method_str().c_str(), r->url().c_str(),
|
||||||
r->method_str().c_str(), r->url().c_str(), r->content_length(),
|
r->content_length(), hm->is_chunked());
|
||||||
hm->is_chunked(), hm->is_infinite_chunked());
|
|
||||||
|
|
||||||
// use cors server mux to serve http request, which will proxy to mux.
|
// use cors server mux to serve http request, which will proxy to mux.
|
||||||
if ((err = cors->serve_http(w, r)) != srs_success) {
|
if ((err = cors->serve_http(w, r)) != srs_success) {
|
||||||
|
|
|
@ -449,15 +449,11 @@ public:
|
||||||
//
|
//
|
||||||
// There are some modes to determine the length of body:
|
// There are some modes to determine the length of body:
|
||||||
// 1. content-length and chunked.
|
// 1. content-length and chunked.
|
||||||
// 2. user confirmed infinite chunked.
|
// 2. infinite chunked.
|
||||||
// 3. no body or user not confirmed infinite chunked.
|
// 3. no body.
|
||||||
// For example:
|
// For example:
|
||||||
// ISrsHttpMessage* r = ...;
|
// ISrsHttpMessage* r = ...;
|
||||||
// while (!r->eof()) r->read(); // Read in mode 1 or 3.
|
// while (!r->eof()) r->read(); // Read in mode 1 or 3.
|
||||||
// For some server, we can confirm the body is infinite chunked:
|
|
||||||
// ISrsHttpMessage* r = ...;
|
|
||||||
// r->enter_infinite_chunked();
|
|
||||||
// while (!r->eof()) r->read(); // Read in mode 2
|
|
||||||
// @rmark for mode 2, the infinite chunked, all left data is body.
|
// @rmark for mode 2, the infinite chunked, all left data is body.
|
||||||
class ISrsHttpMessage
|
class ISrsHttpMessage
|
||||||
{
|
{
|
||||||
|
@ -492,10 +488,6 @@ public:
|
||||||
// @return the REST id; -1 if not matched.
|
// @return the REST id; -1 if not matched.
|
||||||
virtual std::string parse_rest_id(std::string pattern) = 0;
|
virtual std::string parse_rest_id(std::string pattern) = 0;
|
||||||
public:
|
public:
|
||||||
// The left all data is chunked body, the infinite chunked mode,
|
|
||||||
// which is chunked encoding without chunked header.
|
|
||||||
// @remark error when message is in chunked or content-length specified.
|
|
||||||
virtual srs_error_t enter_infinite_chunked() = 0;
|
|
||||||
// Read body to string.
|
// Read body to string.
|
||||||
// @remark for small http body.
|
// @remark for small http body.
|
||||||
virtual srs_error_t body_read_all(std::string& body) = 0;
|
virtual srs_error_t body_read_all(std::string& body) = 0;
|
||||||
|
|
|
@ -291,7 +291,6 @@ SrsHttpMessage::SrsHttpMessage(ISrsReader* reader, SrsFastStream* buffer) : ISrs
|
||||||
{
|
{
|
||||||
owner_conn = NULL;
|
owner_conn = NULL;
|
||||||
chunked = false;
|
chunked = false;
|
||||||
infinite_chunked = false;
|
|
||||||
_uri = new SrsHttpUri();
|
_uri = new SrsHttpUri();
|
||||||
_body = new SrsHttpResponseReader(this, reader, buffer);
|
_body = new SrsHttpResponseReader(this, reader, buffer);
|
||||||
|
|
||||||
|
@ -476,11 +475,6 @@ bool SrsHttpMessage::is_keep_alive()
|
||||||
return _keep_alive;
|
return _keep_alive;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsHttpMessage::is_infinite_chunked()
|
|
||||||
{
|
|
||||||
return infinite_chunked;
|
|
||||||
}
|
|
||||||
|
|
||||||
string SrsHttpMessage::uri()
|
string SrsHttpMessage::uri()
|
||||||
{
|
{
|
||||||
std::string uri = _uri->get_schema();
|
std::string uri = _uri->get_schema();
|
||||||
|
@ -550,23 +544,6 @@ std::string SrsHttpMessage::parse_rest_id(string pattern)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsHttpMessage::enter_infinite_chunked()
|
|
||||||
{
|
|
||||||
srs_error_t err = srs_success;
|
|
||||||
|
|
||||||
if (infinite_chunked) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_chunked() || content_length() != -1) {
|
|
||||||
return srs_error_new(ERROR_HTTP_DATA_INVALID, "not infinited chunked");
|
|
||||||
}
|
|
||||||
|
|
||||||
infinite_chunked = true;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
srs_error_t SrsHttpMessage::body_read_all(string& body)
|
srs_error_t SrsHttpMessage::body_read_all(string& body)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
@ -975,17 +952,10 @@ srs_error_t SrsHttpResponseReader::read(void* data, size_t nb_data, ssize_t* nb_
|
||||||
return read_specified(data, nb_data, nb_read);
|
return read_specified(data, nb_data, nb_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
// infinite chunked mode, directly read.
|
// Infinite chunked mode.
|
||||||
if (owner->is_infinite_chunked()) {
|
// If not chunked encoding, and no content-length, it's infinite chunked.
|
||||||
srs_assert(!owner->is_chunked() && owner->content_length() == -1);
|
// In this mode, all body is data and never EOF util socket closed.
|
||||||
return read_specified(data, nb_data, nb_read);
|
return read_specified(data, nb_data, nb_read);
|
||||||
}
|
|
||||||
|
|
||||||
// infinite chunked mode, but user not set it,
|
|
||||||
// we think there is no data left.
|
|
||||||
is_eof = true;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsHttpResponseReader::read_chunked(void* data, size_t nb_data, ssize_t* nb_read)
|
srs_error_t SrsHttpResponseReader::read_chunked(void* data, size_t nb_data, ssize_t* nb_read)
|
||||||
|
|
|
@ -99,8 +99,6 @@ private:
|
||||||
// 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 infinite chunked.
|
|
||||||
bool infinite_chunked;
|
|
||||||
// Use a buffer to read and send ts file.
|
// Use a buffer to read and send ts file.
|
||||||
// The transport connection, can be NULL.
|
// The transport connection, can be NULL.
|
||||||
ISrsConnection* owner_conn;
|
ISrsConnection* owner_conn;
|
||||||
|
@ -157,9 +155,6 @@ public:
|
||||||
virtual bool is_http_options();
|
virtual bool is_http_options();
|
||||||
// Whether body is chunked encoding, for reader only.
|
// Whether body is chunked encoding, for reader only.
|
||||||
virtual bool is_chunked();
|
virtual bool is_chunked();
|
||||||
// Whether body is infinite chunked encoding.
|
|
||||||
// @remark set by enter_infinite_chunked.
|
|
||||||
virtual bool is_infinite_chunked();
|
|
||||||
// Whether should keep the connection alive.
|
// Whether should keep the connection alive.
|
||||||
virtual bool is_keep_alive();
|
virtual bool is_keep_alive();
|
||||||
// The uri contains the host and path.
|
// The uri contains the host and path.
|
||||||
|
@ -173,8 +168,6 @@ public:
|
||||||
virtual std::string ext();
|
virtual std::string ext();
|
||||||
// Get the RESTful matched id.
|
// Get the RESTful matched id.
|
||||||
virtual std::string parse_rest_id(std::string pattern);
|
virtual std::string parse_rest_id(std::string pattern);
|
||||||
public:
|
|
||||||
virtual srs_error_t enter_infinite_chunked();
|
|
||||||
public:
|
public:
|
||||||
// Read body to string.
|
// Read body to string.
|
||||||
// @remark for small http body.
|
// @remark for small http body.
|
||||||
|
|
|
@ -480,7 +480,7 @@ VOID TEST(TCPServerTest, WritevIOVC)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID TEST(TCPServerTest, MessageConnection)
|
VOID TEST(HTTPServerTest, MessageConnection)
|
||||||
{
|
{
|
||||||
srs_error_t err;
|
srs_error_t err;
|
||||||
|
|
||||||
|
@ -534,7 +534,6 @@ VOID TEST(TCPServerTest, MessageConnection)
|
||||||
if (true) {
|
if (true) {
|
||||||
SrsHttpMessage m;
|
SrsHttpMessage m;
|
||||||
EXPECT_TRUE(m.is_keep_alive());
|
EXPECT_TRUE(m.is_keep_alive());
|
||||||
EXPECT_FALSE(m.is_infinite_chunked());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
|
@ -562,42 +561,7 @@ VOID TEST(TCPServerTest, MessageConnection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID TEST(TCPServerTest, MessageInfinityChunked)
|
VOID TEST(HTTPServerTest, MessageTurnRequest)
|
||||||
{
|
|
||||||
srs_error_t err;
|
|
||||||
|
|
||||||
if (true) {
|
|
||||||
SrsHttpMessage m;
|
|
||||||
EXPECT_FALSE(m.is_infinite_chunked());
|
|
||||||
HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked());
|
|
||||||
EXPECT_TRUE(m.is_infinite_chunked());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (true) {
|
|
||||||
SrsHttpMessage m;
|
|
||||||
HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked());
|
|
||||||
HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked());
|
|
||||||
EXPECT_TRUE(m.is_infinite_chunked());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (true) {
|
|
||||||
SrsHttpMessage m;
|
|
||||||
SrsHttpHeader hdr;
|
|
||||||
hdr.set("Transfer-Encoding", "chunked");
|
|
||||||
m.set_header(&hdr, false);
|
|
||||||
HELPER_EXPECT_FAILED(m.enter_infinite_chunked());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (true) {
|
|
||||||
SrsHttpMessage m;
|
|
||||||
SrsHttpHeader hdr;
|
|
||||||
hdr.set("Content-Length", "100");
|
|
||||||
m.set_header(&hdr, false);
|
|
||||||
HELPER_EXPECT_FAILED(m.enter_infinite_chunked());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID TEST(TCPServerTest, MessageTurnRequest)
|
|
||||||
{
|
{
|
||||||
srs_error_t err;
|
srs_error_t err;
|
||||||
|
|
||||||
|
@ -645,7 +609,65 @@ VOID TEST(TCPServerTest, MessageTurnRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID TEST(TCPServerTest, MessageWritev)
|
VOID TEST(HTTPServerTest, ContentLength)
|
||||||
|
{
|
||||||
|
srs_error_t err;
|
||||||
|
|
||||||
|
// For infinite chunked mode, all data is content.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
io.append("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n");
|
||||||
|
|
||||||
|
SrsHttpParser hp; HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_RESPONSE, false));
|
||||||
|
ISrsHttpMessage* msg = NULL; HELPER_ASSERT_SUCCESS(hp.parse_message(&io, &msg));
|
||||||
|
|
||||||
|
char buf[32]; ssize_t nread = 0;
|
||||||
|
ISrsHttpResponseReader* r = msg->body_reader();
|
||||||
|
|
||||||
|
io.append("Hello");
|
||||||
|
HELPER_ARRAY_INIT(buf, sizeof(buf), 0);
|
||||||
|
HELPER_ASSERT_SUCCESS(r->read(buf, 5, &nread));
|
||||||
|
EXPECT_EQ(5, nread);
|
||||||
|
EXPECT_STREQ("Hello", buf);
|
||||||
|
|
||||||
|
io.append("World!");
|
||||||
|
HELPER_ARRAY_INIT(buf, sizeof(buf), 0);
|
||||||
|
HELPER_ASSERT_SUCCESS(r->read(buf, 6, &nread));
|
||||||
|
EXPECT_EQ(6, nread);
|
||||||
|
EXPECT_STREQ("World!", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID TEST(HTTPServerTest, HTTPChunked)
|
||||||
|
{
|
||||||
|
srs_error_t err;
|
||||||
|
|
||||||
|
// For infinite chunked mode, all data is content.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
io.append("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
||||||
|
|
||||||
|
SrsHttpParser hp; HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_RESPONSE, false));
|
||||||
|
ISrsHttpMessage* msg = NULL; HELPER_ASSERT_SUCCESS(hp.parse_message(&io, &msg));
|
||||||
|
|
||||||
|
char buf[32]; ssize_t nread = 0;
|
||||||
|
ISrsHttpResponseReader* r = msg->body_reader();
|
||||||
|
|
||||||
|
io.append("5\r\nHello\r\n");
|
||||||
|
HELPER_ARRAY_INIT(buf, sizeof(buf), 0);
|
||||||
|
HELPER_ASSERT_SUCCESS(r->read(buf, 5, &nread));
|
||||||
|
EXPECT_EQ(5, nread);
|
||||||
|
EXPECT_STREQ("Hello", buf);
|
||||||
|
|
||||||
|
io.append("6\r\nWorld!\r\n");
|
||||||
|
HELPER_ARRAY_INIT(buf, sizeof(buf), 0);
|
||||||
|
HELPER_ASSERT_SUCCESS(r->read(buf, 6, &nread));
|
||||||
|
EXPECT_EQ(6, nread);
|
||||||
|
EXPECT_STREQ("World!", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID TEST(HTTPServerTest, InfiniteChunked)
|
||||||
{
|
{
|
||||||
srs_error_t err;
|
srs_error_t err;
|
||||||
|
|
||||||
|
@ -657,12 +679,6 @@ VOID TEST(TCPServerTest, MessageWritev)
|
||||||
SrsHttpParser hp; HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_RESPONSE, false));
|
SrsHttpParser hp; HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_RESPONSE, false));
|
||||||
ISrsHttpMessage* msg = NULL; HELPER_ASSERT_SUCCESS(hp.parse_message(&io, &msg));
|
ISrsHttpMessage* msg = NULL; HELPER_ASSERT_SUCCESS(hp.parse_message(&io, &msg));
|
||||||
|
|
||||||
if (true) {
|
|
||||||
SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(msg);
|
|
||||||
ASSERT_TRUE(hm != NULL);
|
|
||||||
hm->enter_infinite_chunked();
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[32]; ssize_t nread = 0;
|
char buf[32]; ssize_t nread = 0;
|
||||||
ISrsHttpResponseReader* r = msg->body_reader();
|
ISrsHttpResponseReader* r = msg->body_reader();
|
||||||
|
|
||||||
|
@ -678,6 +694,11 @@ VOID TEST(TCPServerTest, MessageWritev)
|
||||||
EXPECT_EQ(8, nread);
|
EXPECT_EQ(8, nread);
|
||||||
EXPECT_STREQ("\r\nWorld!", buf);
|
EXPECT_STREQ("\r\nWorld!", buf);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID TEST(HTTPServerTest, MessageWritev)
|
||||||
|
{
|
||||||
|
srs_error_t err;
|
||||||
|
|
||||||
// Directly writev, merge to one chunk.
|
// Directly writev, merge to one chunk.
|
||||||
if (true) {
|
if (true) {
|
||||||
|
@ -1174,7 +1195,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
VOID TEST(TCPServerTest, HTTPClientUtility)
|
VOID TEST(HTTPClientTest, HTTPClientUtility)
|
||||||
{
|
{
|
||||||
srs_error_t err;
|
srs_error_t err;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue