mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	Enhance HTTP response write for final_request.
This commit is contained in:
		
							parent
							
								
									e27cc059e4
								
							
						
					
					
						commit
						81947df819
					
				
					 3 changed files with 107 additions and 3 deletions
				
			
		|  | @ -145,6 +145,7 @@ For previous versions, please read: | |||
| 
 | ||||
| ## V3 changes | ||||
| 
 | ||||
| * v3.0, 2019-12-17, Enhance HTTP response write for final_request. | ||||
| * v3.0, 2019-12-17, Refactor HTTP stream to disconnect client when unpublish. | ||||
| * v3.0, 2019-12-17, Fix HTTP-FLV and VOD-FLV conflicting bug. | ||||
| * v3.0, 2019-12-17, Refactor HttpResponseWriter.write, default to single text mode. | ||||
|  |  | |||
|  | @ -619,10 +619,17 @@ SrsHttpResponseWriter::~SrsHttpResponseWriter() | |||
| 
 | ||||
| srs_error_t SrsHttpResponseWriter::final_request() | ||||
| { | ||||
|     srs_error_t err = srs_success; | ||||
| 
 | ||||
|     // write the header data in memory.
 | ||||
|     if (!header_wrote) { | ||||
|         write_header(SRS_CONSTS_HTTP_OK); | ||||
|     } | ||||
| 
 | ||||
|     // whatever header is wrote, we should try to send header.
 | ||||
|     if ((err = send_header(NULL, 0)) != srs_success) { | ||||
|         return srs_error_wrap(err, "send header"); | ||||
|     } | ||||
|      | ||||
|     // complete the chunked encoding.
 | ||||
|     if (content_length == -1) { | ||||
|  | @ -666,7 +673,7 @@ srs_error_t SrsHttpResponseWriter::write(char* data, int size) | |||
|     } | ||||
|      | ||||
|     // ignore NULL content.
 | ||||
|     if (!data) { | ||||
|     if (!data || size <= 0) { | ||||
|         return err; | ||||
|     } | ||||
|      | ||||
|  | @ -811,7 +818,7 @@ srs_error_t SrsHttpResponseWriter::send_header(char* data, int size) | |||
|      | ||||
|     // detect content type
 | ||||
|     if (srs_go_http_body_allowd(status)) { | ||||
|         if (hdr->content_type().empty()) { | ||||
|         if (data && hdr->content_type().empty()) { | ||||
|             hdr->set_content_type(srs_go_http_detect(data, size)); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -108,6 +108,16 @@ string mock_http_response(int status, string content) | |||
|     return ss.str(); | ||||
| } | ||||
| 
 | ||||
| string mock_http_response2(int status, string content) | ||||
| { | ||||
|     stringstream ss; | ||||
|     ss << "HTTP/1.1 " << status << " " << srs_generate_http_status_text(status) << "\r\n" | ||||
|         << "Transfer-Encoding: chunked" << "\r\n" | ||||
|         << "\r\n" | ||||
|         << content; | ||||
|     return ss.str(); | ||||
| } | ||||
| 
 | ||||
| class MockFileReaderFactory : public ISrsFileReaderFactory | ||||
| { | ||||
| public: | ||||
|  | @ -149,6 +159,9 @@ bool _mock_srs_path_not_exists(std::string /*path*/) | |||
| #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()) | ||||
| 
 | ||||
| #define __MOCK_HTTP_EXPECT_STREQ2(status, text, w) \ | ||||
|         EXPECT_STREQ(mock_http_response2(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()); | ||||
|  | @ -169,6 +182,7 @@ VOID TEST(ProtocolHTTPTest, ResponseDetect) | |||
| 
 | ||||
| VOID TEST(ProtocolHTTPTest, ResponseWriter) | ||||
| { | ||||
|     // If directly write string, response with content-length.
 | ||||
|     if (true) { | ||||
|         MockResponseWriter w; | ||||
| 
 | ||||
|  | @ -177,6 +191,70 @@ VOID TEST(ProtocolHTTPTest, ResponseWriter) | |||
| 
 | ||||
|         __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w); | ||||
|     } | ||||
| 
 | ||||
|     // Response with specified length string, response with content-length.
 | ||||
|     if (true) { | ||||
|         MockResponseWriter w; | ||||
| 
 | ||||
|         char msg[] = "Hello, world!"; | ||||
| 
 | ||||
|         w.header()->set_content_type("text/plain; charset=utf-8"); | ||||
|         w.header()->set_content_length(sizeof(msg) - 1); | ||||
|         w.write_header(SRS_CONSTS_HTTP_OK); | ||||
|         w.write((char*)msg, sizeof(msg) - 1); | ||||
|         w.final_request(); | ||||
| 
 | ||||
|         __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w); | ||||
|     } | ||||
| 
 | ||||
|     // If set content-length to 0 then final_request, send an empty resonse with content-length 0.
 | ||||
|     if (true) { | ||||
|         MockResponseWriter w; | ||||
| 
 | ||||
|         w.header()->set_content_length(0); | ||||
|         w.write_header(SRS_CONSTS_HTTP_OK); | ||||
|         w.final_request(); | ||||
| 
 | ||||
|         __MOCK_HTTP_EXPECT_STREQ(200, "", w); | ||||
|     } | ||||
| 
 | ||||
|     // If set content-length to 0 then write, send an empty resonse with content-length 0.
 | ||||
|     if (true) { | ||||
|         MockResponseWriter w; | ||||
| 
 | ||||
|         w.header()->set_content_length(0); | ||||
|         w.write_header(SRS_CONSTS_HTTP_OK); | ||||
|         w.write(NULL, 0); | ||||
| 
 | ||||
|         __MOCK_HTTP_EXPECT_STREQ(200, "", w); | ||||
|     } | ||||
| 
 | ||||
|     // If write_header without content-length, enter chunked encoding mode.
 | ||||
|     if (true) { | ||||
|         MockResponseWriter w; | ||||
| 
 | ||||
|         w.header()->set_content_type("application/octet-stream"); | ||||
|         w.write_header(SRS_CONSTS_HTTP_OK); | ||||
|         w.write((char*)"Hello", 5); | ||||
|         w.write((char*)", world!", 8); | ||||
|         w.final_request(); | ||||
| 
 | ||||
|         __MOCK_HTTP_EXPECT_STREQ2(200, "5\r\nHello\r\n8\r\n, world!\r\n0\r\n\r\n", w); | ||||
|     } | ||||
| 
 | ||||
|     // If directly write empty string, sent an empty response with content-length 0
 | ||||
|     if (true) { | ||||
|         MockResponseWriter w; | ||||
|         w.write(NULL, 0); | ||||
|         __MOCK_HTTP_EXPECT_STREQ(200, "", w); | ||||
|     } | ||||
| 
 | ||||
|     // If directly final request, response with EOF of chunked.
 | ||||
|     if (true) { | ||||
|         MockResponseWriter w; | ||||
|         w.final_request(); | ||||
|         __MOCK_HTTP_EXPECT_STREQ2(200, "0\r\n\r\n", w); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| VOID TEST(ProtocolHTTPTest, ResponseHTTPError) | ||||
|  | @ -356,7 +434,24 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers) | |||
| 
 | ||||
|         MockResponseWriter w; | ||||
|         SrsHttpMessage r(NULL, NULL); | ||||
|         HELPER_ASSERT_SUCCESS(r.set_url("/index.mp4?start=2", false)); | ||||
|         HELPER_ASSERT_SUCCESS(r.set_url("/index.mp4?range=12-3", false)); | ||||
| 
 | ||||
|         HELPER_ASSERT_SUCCESS(h.serve_http(&w, &r)); | ||||
|         __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w); | ||||
|     } | ||||
| 
 | ||||
|     if (true) { | ||||
|         SrsHttpMuxEntry e; | ||||
|         e.pattern = "/"; | ||||
| 
 | ||||
|         SrsHttpFileServer h("/tmp"); | ||||
|         h.set_fs_factory(new MockFileReaderFactory("Hello, world!")); | ||||
|         h.set_path_check(_mock_srs_path_always_exists); | ||||
|         h.entry = &e; | ||||
| 
 | ||||
|         MockResponseWriter w; | ||||
|         SrsHttpMessage r(NULL, NULL); | ||||
|         HELPER_ASSERT_SUCCESS(r.set_url("/index.mp4?range=2-3", false)); | ||||
| 
 | ||||
|         HELPER_ASSERT_SUCCESS(h.serve_http(&w, &r)); | ||||
|         __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w); | ||||
|  | @ -444,6 +539,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers) | |||
| 
 | ||||
|     if (true) { | ||||
|         SrsHttpRedirectHandler h("/api", 500); | ||||
|         EXPECT_FALSE(h.is_not_found()); | ||||
| 
 | ||||
|         MockResponseWriter w; | ||||
|         SrsHttpMessage r(NULL, NULL); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue