Refactor HttpResponseWriter.write, default to single text mode.

pull/1568/head
winlin 5 years ago
parent 8cdb7cc727
commit d9842b0371

@ -117,6 +117,7 @@ srs_error_t SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMe
// write http header for ts.
w->header()->set_content_length((int)(sizeof(flv_header) + sh_size + left));
w->header()->set_content_type("video/x-flv");
w->write_header(SRS_CONSTS_HTTP_OK);
// write flv header and sequence header.
if ((err = w->write(flv_header, sizeof(flv_header))) != srs_success) {
@ -170,8 +171,6 @@ srs_error_t SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMe
// write http header for ts.
w->header()->set_content_length(left);
w->header()->set_content_type("video/mp4");
// status code 206 to make dash.as happy.
w->write_header(SRS_CONSTS_HTTP_PartialContent);
// response the content range header.

@ -540,6 +540,9 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
return srs_error_new(ERROR_HTTP_LIVE_STREAM_EXT, "invalid pattern=%s", entry->pattern.c_str());
}
SrsAutoFree(ISrsBufferEncoder, enc);
// Enter chunked mode, because we didn't set the content-length.
w->write_header(SRS_CONSTS_HTTP_OK);
// create consumer of souce, ignore gop cache, use the audio gop cache.
SrsConsumer* consumer = NULL;

@ -446,6 +446,9 @@ srs_error_t SrsHttpFileServer::serve_file(ISrsHttpResponseWriter* w, ISrsHttpMes
w->header()->set_content_type(_mime[ext]);
}
}
// Enter chunked mode, because we didn't set the content-length.
w->write_header(SRS_CONSTS_HTTP_OK);
// write body.
int64_t left = length;

@ -150,7 +150,11 @@ public:
// A ResponseWriter interface is used by an HTTP handler to
// construct an HTTP response.
// Usage 1, response with specified length content:
// Usage 0, response with a message once:
// ISrsHttpResponseWriter* w; // create or get response.
// std::string msg = "Hello, HTTP!";
// w->write((char*)msg.data(), (int)msg.length());
// Usage 1, response with specified length content, same to #0:
// ISrsHttpResponseWriter* w; // create or get response.
// std::string msg = "Hello, HTTP!";
// w->header()->set_content_type("text/plain; charset=utf-8");

@ -647,6 +647,10 @@ srs_error_t SrsHttpResponseWriter::write(char* data, int size)
// write the header data in memory.
if (!header_wrote) {
if (hdr->content_type().empty()) {
hdr->set_content_type("text/plain; charset=utf-8");
}
hdr->set_content_length(size);
write_header(SRS_CONSTS_HTTP_OK);
}

@ -108,6 +108,47 @@ string mock_http_response(int status, string content)
return ss.str();
}
class MockFileReaderFactory : public ISrsFileReaderFactory
{
public:
string bytes;
MockFileReaderFactory(string data) {
bytes = data;
}
virtual ~MockFileReaderFactory() {
}
virtual SrsFileReader* create_file_reader() {
return new MockSrsFileReader((const char*)bytes.data(), (int)bytes.length());
}
};
class MockHttpHandler : public ISrsHttpHandler
{
public:
string bytes;
MockHttpHandler(string data) {
bytes = data;
}
virtual ~MockHttpHandler() {
}
virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* /*r*/) {
return w->write((char*)bytes.data(), (int)bytes.length());
}
};
bool _mock_srs_path_always_exists(std::string /*path*/)
{
return true;
}
bool _mock_srs_path_not_exists(std::string /*path*/)
{
return false;
}
#define __MOCK_HTTP_EXPECT_STREQ(status, text, w) \
EXPECT_STREQ(mock_http_response(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str())
VOID TEST(ProtocolHTTPTest, StatusCode2Text)
{
EXPECT_STREQ(SRS_CONSTS_HTTP_OK_str, srs_generate_http_status_text(SRS_CONSTS_HTTP_OK).c_str());
@ -123,10 +164,20 @@ VOID TEST(ProtocolHTTPTest, StatusCode2Text)
VOID TEST(ProtocolHTTPTest, ResponseDetect)
{
EXPECT_STREQ("application/octet-stream", srs_go_http_detect(NULL, 0).c_str());
EXPECT_STREQ("application/octet-stream", srs_go_http_detect((char*)"Hello, world!", 0).c_str());
}
#define __MOCK_HTTP_EXPECT_STREQ(status, text, w) \
EXPECT_STREQ(mock_http_response(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str())
VOID TEST(ProtocolHTTPTest, ResponseWriter)
{
if (true) {
MockResponseWriter w;
char msg[] = "Hello, world!";
w.write((char*)msg, sizeof(msg) - 1);
__MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
}
}
VOID TEST(ProtocolHTTPTest, ResponseHTTPError)
{
@ -137,6 +188,18 @@ VOID TEST(ProtocolHTTPTest, ResponseHTTPError)
HELPER_EXPECT_SUCCESS(srs_go_http_error(&w, SRS_CONSTS_HTTP_Found));
__MOCK_HTTP_EXPECT_STREQ(302, "Found", w);
}
if (true) {
MockResponseWriter w;
HELPER_EXPECT_SUCCESS(srs_go_http_error(&w, SRS_CONSTS_HTTP_InternalServerError));
__MOCK_HTTP_EXPECT_STREQ(500, "Internal Server Error", w);
}
if (true) {
MockResponseWriter w;
HELPER_EXPECT_SUCCESS(srs_go_http_error(&w, SRS_CONSTS_HTTP_ServiceUnavailable));
__MOCK_HTTP_EXPECT_STREQ(503, "Service Unavailable", w);
}
}
VOID TEST(ProtocolHTTPTest, HTTPHeader)
@ -173,28 +236,24 @@ VOID TEST(ProtocolHTTPTest, HTTPHeader)
srs_freep(o);
}
class MockFileReaderFactory : public ISrsFileReaderFactory
VOID TEST(ProtocolHTTPTest, HTTPServerMuxer)
{
public:
string bytes;
MockFileReaderFactory(string data) {
bytes = data;
}
virtual ~MockFileReaderFactory() {
}
virtual SrsFileReader* create_file_reader() {
return new MockSrsFileReader((const char*)bytes.data(), (int)bytes.length());
}
};
srs_error_t err;
bool _mock_srs_path_always_exists(std::string /*path*/)
{
return true;
}
if (true) {
SrsHttpServeMux s;
HELPER_ASSERT_SUCCESS(s.initialize());
bool _mock_srs_path_not_exists(std::string /*path*/)
{
return false;
MockHttpHandler* hroot = new MockHttpHandler("Hello, world!");
HELPER_ASSERT_SUCCESS(s.handle("/", hroot));
MockResponseWriter w;
SrsHttpMessage r(NULL, NULL);
HELPER_ASSERT_SUCCESS(r.set_url("/index.html", false));
HELPER_ASSERT_SUCCESS(s.serve_http(&w, &r));
__MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w);
}
}
VOID TEST(ProtocolHTTPTest, VodStreamHandlers)

Loading…
Cancel
Save