正在显示
13 个修改的文件
包含
1323 行增加
和
1202 行删除
| @@ -82,14 +82,14 @@ void SrsHttpHeartbeat::heartbeat() | @@ -82,14 +82,14 @@ void SrsHttpHeartbeat::heartbeat() | ||
| 82 | return; | 82 | return; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | - SrsHttpMessage* msg = NULL; | 85 | + ISrsHttpMessage* msg = NULL; |
| 86 | if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { | 86 | if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { |
| 87 | srs_info("http post hartbeart uri failed. " | 87 | srs_info("http post hartbeart uri failed. " |
| 88 | "url=%s, request=%s, response=%s, ret=%d", | 88 | "url=%s, request=%s, response=%s, ret=%d", |
| 89 | url.c_str(), req.c_str(), res.c_str(), ret); | 89 | url.c_str(), req.c_str(), res.c_str(), ret); |
| 90 | return; | 90 | return; |
| 91 | } | 91 | } |
| 92 | - SrsAutoFree(SrsHttpMessage, msg); | 92 | + SrsAutoFree(ISrsHttpMessage, msg); |
| 93 | 93 | ||
| 94 | std::string res; | 94 | std::string res; |
| 95 | if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { | 95 | if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { |
| @@ -25,726 +25,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -25,726 +25,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | 25 | ||
| 26 | #ifdef SRS_AUTO_HTTP_PARSER | 26 | #ifdef SRS_AUTO_HTTP_PARSER |
| 27 | 27 | ||
| 28 | -#include <stdlib.h> | ||
| 29 | -#include <sys/stat.h> | ||
| 30 | -#include <algorithm> | 28 | +#include <sstream> |
| 31 | using namespace std; | 29 | using namespace std; |
| 32 | 30 | ||
| 33 | #include <srs_kernel_error.hpp> | 31 | #include <srs_kernel_error.hpp> |
| 34 | #include <srs_kernel_log.hpp> | 32 | #include <srs_kernel_log.hpp> |
| 35 | #include <srs_app_st_socket.hpp> | 33 | #include <srs_app_st_socket.hpp> |
| 36 | -#include <srs_app_http_api.hpp> | ||
| 37 | -#include <srs_app_http_conn.hpp> | ||
| 38 | -#include <srs_app_json.hpp> | ||
| 39 | -#include <srs_kernel_utility.hpp> | ||
| 40 | -#include <srs_rtmp_buffer.hpp> | ||
| 41 | -#include <srs_kernel_file.hpp> | ||
| 42 | -#include <srs_core_autofree.hpp> | ||
| 43 | -#include <srs_rtmp_buffer.hpp> | ||
| 44 | #include <srs_rtmp_sdk.hpp> | 34 | #include <srs_rtmp_sdk.hpp> |
| 35 | +#include <srs_rtmp_buffer.hpp> | ||
| 36 | +#include <srs_kernel_utility.hpp> | ||
| 45 | #include <srs_rtmp_utility.hpp> | 37 | #include <srs_rtmp_utility.hpp> |
| 46 | - | ||
| 47 | -#define SRS_DEFAULT_HTTP_PORT 80 | ||
| 48 | - | ||
| 49 | -// for http parser macros | ||
| 50 | -#define SRS_CONSTS_HTTP_OPTIONS HTTP_OPTIONS | ||
| 51 | -#define SRS_CONSTS_HTTP_GET HTTP_GET | ||
| 52 | -#define SRS_CONSTS_HTTP_POST HTTP_POST | ||
| 53 | -#define SRS_CONSTS_HTTP_PUT HTTP_PUT | ||
| 54 | -#define SRS_CONSTS_HTTP_DELETE HTTP_DELETE | ||
| 55 | - | ||
| 56 | -// for ead all of http body, read each time. | ||
| 57 | -#define SRS_HTTP_READ_CACHE_BYTES 4096 | ||
| 58 | - | ||
| 59 | -#define SRS_HTTP_DEFAULT_PAGE "index.html" | ||
| 60 | - | ||
| 61 | -int srs_http_response_json(ISrsHttpResponseWriter* w, string data) | ||
| 62 | -{ | ||
| 63 | - w->header()->set_content_length(data.length()); | ||
| 64 | - w->header()->set_content_type("application/json"); | ||
| 65 | - | ||
| 66 | - return w->write((char*)data.data(), (int)data.length()); | ||
| 67 | -} | ||
| 68 | - | ||
| 69 | -// get the status text of code. | ||
| 70 | -string srs_generate_http_status_text(int status) | ||
| 71 | -{ | ||
| 72 | - static std::map<int, std::string> _status_map; | ||
| 73 | - if (_status_map.empty()) { | ||
| 74 | - _status_map[SRS_CONSTS_HTTP_Continue ] = SRS_CONSTS_HTTP_Continue_str ; | ||
| 75 | - _status_map[SRS_CONSTS_HTTP_SwitchingProtocols ] = SRS_CONSTS_HTTP_SwitchingProtocols_str ; | ||
| 76 | - _status_map[SRS_CONSTS_HTTP_OK ] = SRS_CONSTS_HTTP_OK_str ; | ||
| 77 | - _status_map[SRS_CONSTS_HTTP_Created ] = SRS_CONSTS_HTTP_Created_str ; | ||
| 78 | - _status_map[SRS_CONSTS_HTTP_Accepted ] = SRS_CONSTS_HTTP_Accepted_str ; | ||
| 79 | - _status_map[SRS_CONSTS_HTTP_NonAuthoritativeInformation ] = SRS_CONSTS_HTTP_NonAuthoritativeInformation_str ; | ||
| 80 | - _status_map[SRS_CONSTS_HTTP_NoContent ] = SRS_CONSTS_HTTP_NoContent_str ; | ||
| 81 | - _status_map[SRS_CONSTS_HTTP_ResetContent ] = SRS_CONSTS_HTTP_ResetContent_str ; | ||
| 82 | - _status_map[SRS_CONSTS_HTTP_PartialContent ] = SRS_CONSTS_HTTP_PartialContent_str ; | ||
| 83 | - _status_map[SRS_CONSTS_HTTP_MultipleChoices ] = SRS_CONSTS_HTTP_MultipleChoices_str ; | ||
| 84 | - _status_map[SRS_CONSTS_HTTP_MovedPermanently ] = SRS_CONSTS_HTTP_MovedPermanently_str ; | ||
| 85 | - _status_map[SRS_CONSTS_HTTP_Found ] = SRS_CONSTS_HTTP_Found_str ; | ||
| 86 | - _status_map[SRS_CONSTS_HTTP_SeeOther ] = SRS_CONSTS_HTTP_SeeOther_str ; | ||
| 87 | - _status_map[SRS_CONSTS_HTTP_NotModified ] = SRS_CONSTS_HTTP_NotModified_str ; | ||
| 88 | - _status_map[SRS_CONSTS_HTTP_UseProxy ] = SRS_CONSTS_HTTP_UseProxy_str ; | ||
| 89 | - _status_map[SRS_CONSTS_HTTP_TemporaryRedirect ] = SRS_CONSTS_HTTP_TemporaryRedirect_str ; | ||
| 90 | - _status_map[SRS_CONSTS_HTTP_BadRequest ] = SRS_CONSTS_HTTP_BadRequest_str ; | ||
| 91 | - _status_map[SRS_CONSTS_HTTP_Unauthorized ] = SRS_CONSTS_HTTP_Unauthorized_str ; | ||
| 92 | - _status_map[SRS_CONSTS_HTTP_PaymentRequired ] = SRS_CONSTS_HTTP_PaymentRequired_str ; | ||
| 93 | - _status_map[SRS_CONSTS_HTTP_Forbidden ] = SRS_CONSTS_HTTP_Forbidden_str ; | ||
| 94 | - _status_map[SRS_CONSTS_HTTP_NotFound ] = SRS_CONSTS_HTTP_NotFound_str ; | ||
| 95 | - _status_map[SRS_CONSTS_HTTP_MethodNotAllowed ] = SRS_CONSTS_HTTP_MethodNotAllowed_str ; | ||
| 96 | - _status_map[SRS_CONSTS_HTTP_NotAcceptable ] = SRS_CONSTS_HTTP_NotAcceptable_str ; | ||
| 97 | - _status_map[SRS_CONSTS_HTTP_ProxyAuthenticationRequired ] = SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str ; | ||
| 98 | - _status_map[SRS_CONSTS_HTTP_RequestTimeout ] = SRS_CONSTS_HTTP_RequestTimeout_str ; | ||
| 99 | - _status_map[SRS_CONSTS_HTTP_Conflict ] = SRS_CONSTS_HTTP_Conflict_str ; | ||
| 100 | - _status_map[SRS_CONSTS_HTTP_Gone ] = SRS_CONSTS_HTTP_Gone_str ; | ||
| 101 | - _status_map[SRS_CONSTS_HTTP_LengthRequired ] = SRS_CONSTS_HTTP_LengthRequired_str ; | ||
| 102 | - _status_map[SRS_CONSTS_HTTP_PreconditionFailed ] = SRS_CONSTS_HTTP_PreconditionFailed_str ; | ||
| 103 | - _status_map[SRS_CONSTS_HTTP_RequestEntityTooLarge ] = SRS_CONSTS_HTTP_RequestEntityTooLarge_str ; | ||
| 104 | - _status_map[SRS_CONSTS_HTTP_RequestURITooLarge ] = SRS_CONSTS_HTTP_RequestURITooLarge_str ; | ||
| 105 | - _status_map[SRS_CONSTS_HTTP_UnsupportedMediaType ] = SRS_CONSTS_HTTP_UnsupportedMediaType_str ; | ||
| 106 | - _status_map[SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable ] = SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str ; | ||
| 107 | - _status_map[SRS_CONSTS_HTTP_ExpectationFailed ] = SRS_CONSTS_HTTP_ExpectationFailed_str ; | ||
| 108 | - _status_map[SRS_CONSTS_HTTP_InternalServerError ] = SRS_CONSTS_HTTP_InternalServerError_str ; | ||
| 109 | - _status_map[SRS_CONSTS_HTTP_NotImplemented ] = SRS_CONSTS_HTTP_NotImplemented_str ; | ||
| 110 | - _status_map[SRS_CONSTS_HTTP_BadGateway ] = SRS_CONSTS_HTTP_BadGateway_str ; | ||
| 111 | - _status_map[SRS_CONSTS_HTTP_ServiceUnavailable ] = SRS_CONSTS_HTTP_ServiceUnavailable_str ; | ||
| 112 | - _status_map[SRS_CONSTS_HTTP_GatewayTimeout ] = SRS_CONSTS_HTTP_GatewayTimeout_str ; | ||
| 113 | - _status_map[SRS_CONSTS_HTTP_HTTPVersionNotSupported ] = SRS_CONSTS_HTTP_HTTPVersionNotSupported_str ; | ||
| 114 | - } | ||
| 115 | - | ||
| 116 | - std::string status_text; | ||
| 117 | - if (_status_map.find(status) == _status_map.end()) { | ||
| 118 | - status_text = "Status Unknown"; | ||
| 119 | - } else { | ||
| 120 | - status_text = _status_map[status]; | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - return status_text; | ||
| 124 | -} | ||
| 125 | - | ||
| 126 | -// bodyAllowedForStatus reports whether a given response status code | ||
| 127 | -// permits a body. See RFC2616, section 4.4. | ||
| 128 | -bool srs_go_http_body_allowd(int status) | ||
| 129 | -{ | ||
| 130 | - if (status >= 100 && status <= 199) { | ||
| 131 | - return false; | ||
| 132 | - } else if (status == 204 || status == 304) { | ||
| 133 | - return false; | ||
| 134 | - } | ||
| 135 | - | ||
| 136 | - return true; | ||
| 137 | -} | ||
| 138 | - | ||
| 139 | -// DetectContentType implements the algorithm described | ||
| 140 | -// at http://mimesniff.spec.whatwg.org/ to determine the | ||
| 141 | -// Content-Type of the given data. It considers at most the | ||
| 142 | -// first 512 bytes of data. DetectContentType always returns | ||
| 143 | -// a valid MIME type: if it cannot determine a more specific one, it | ||
| 144 | -// returns "application/octet-stream". | ||
| 145 | -string srs_go_http_detect(char* data, int size) | ||
| 146 | -{ | ||
| 147 | - // detect only when data specified. | ||
| 148 | - if (data) { | ||
| 149 | - } | ||
| 150 | - return "application/octet-stream"; // fallback | ||
| 151 | -} | ||
| 152 | - | ||
| 153 | -// Error replies to the request with the specified error message and HTTP code. | ||
| 154 | -// The error message should be plain text. | ||
| 155 | -int srs_go_http_error(ISrsHttpResponseWriter* w, int code, string error) | ||
| 156 | -{ | ||
| 157 | - int ret = ERROR_SUCCESS; | ||
| 158 | - | ||
| 159 | - w->header()->set_content_type("text/plain; charset=utf-8"); | ||
| 160 | - w->header()->set_content_length(error.length()); | ||
| 161 | - w->write_header(code); | ||
| 162 | - w->write((char*)error.data(), (int)error.length()); | ||
| 163 | - | ||
| 164 | - return ret; | ||
| 165 | -} | ||
| 166 | - | ||
| 167 | -SrsHttpHeader::SrsHttpHeader() | ||
| 168 | -{ | ||
| 169 | -} | ||
| 170 | - | ||
| 171 | -SrsHttpHeader::~SrsHttpHeader() | ||
| 172 | -{ | ||
| 173 | -} | ||
| 174 | - | ||
| 175 | -void SrsHttpHeader::set(string key, string value) | ||
| 176 | -{ | ||
| 177 | - headers[key] = value; | ||
| 178 | -} | ||
| 179 | - | ||
| 180 | -string SrsHttpHeader::get(string key) | ||
| 181 | -{ | ||
| 182 | - std::string v; | ||
| 183 | - | ||
| 184 | - if (headers.find(key) != headers.end()) { | ||
| 185 | - v = headers[key]; | ||
| 186 | - } | ||
| 187 | - | ||
| 188 | - return v; | ||
| 189 | -} | ||
| 190 | - | ||
| 191 | -int64_t SrsHttpHeader::content_length() | ||
| 192 | -{ | ||
| 193 | - std::string cl = get("Content-Length"); | ||
| 194 | - | ||
| 195 | - if (cl.empty()) { | ||
| 196 | - return -1; | ||
| 197 | - } | ||
| 198 | - | ||
| 199 | - return (int64_t)::atof(cl.c_str()); | ||
| 200 | -} | ||
| 201 | - | ||
| 202 | -void SrsHttpHeader::set_content_length(int64_t size) | ||
| 203 | -{ | ||
| 204 | - char buf[64]; | ||
| 205 | - snprintf(buf, sizeof(buf), "%"PRId64, size); | ||
| 206 | - set("Content-Length", buf); | ||
| 207 | -} | ||
| 208 | - | ||
| 209 | -string SrsHttpHeader::content_type() | ||
| 210 | -{ | ||
| 211 | - return get("Content-Type"); | ||
| 212 | -} | ||
| 213 | - | ||
| 214 | -void SrsHttpHeader::set_content_type(string ct) | ||
| 215 | -{ | ||
| 216 | - set("Content-Type", ct); | ||
| 217 | -} | ||
| 218 | - | ||
| 219 | -void SrsHttpHeader::write(stringstream& ss) | ||
| 220 | -{ | ||
| 221 | - std::map<std::string, std::string>::iterator it; | ||
| 222 | - for (it = headers.begin(); it != headers.end(); ++it) { | ||
| 223 | - ss << it->first << ": " << it->second << SRS_HTTP_CRLF; | ||
| 224 | - } | ||
| 225 | -} | ||
| 226 | - | ||
| 227 | -ISrsHttpResponseWriter::ISrsHttpResponseWriter() | ||
| 228 | -{ | ||
| 229 | -} | ||
| 230 | - | ||
| 231 | -ISrsHttpResponseWriter::~ISrsHttpResponseWriter() | ||
| 232 | -{ | ||
| 233 | -} | ||
| 234 | - | ||
| 235 | -ISrsHttpResponseReader::ISrsHttpResponseReader() | ||
| 236 | -{ | ||
| 237 | -} | ||
| 238 | - | ||
| 239 | -ISrsHttpResponseReader::~ISrsHttpResponseReader() | ||
| 240 | -{ | ||
| 241 | -} | ||
| 242 | - | ||
| 243 | -ISrsHttpHandler::ISrsHttpHandler() | ||
| 244 | -{ | ||
| 245 | - entry = NULL; | ||
| 246 | -} | ||
| 247 | - | ||
| 248 | -ISrsHttpHandler::~ISrsHttpHandler() | ||
| 249 | -{ | ||
| 250 | -} | ||
| 251 | - | ||
| 252 | -SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c) | ||
| 253 | -{ | ||
| 254 | - url = u; | ||
| 255 | - code = c; | ||
| 256 | -} | ||
| 257 | - | ||
| 258 | -SrsHttpRedirectHandler::~SrsHttpRedirectHandler() | ||
| 259 | -{ | ||
| 260 | -} | ||
| 261 | - | ||
| 262 | -int SrsHttpRedirectHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 263 | -{ | ||
| 264 | - int ret = ERROR_SUCCESS; | ||
| 265 | - // TODO: FIXME: implements it. | ||
| 266 | - return ret; | ||
| 267 | -} | ||
| 268 | - | ||
| 269 | -SrsHttpNotFoundHandler::SrsHttpNotFoundHandler() | ||
| 270 | -{ | ||
| 271 | -} | ||
| 272 | - | ||
| 273 | -SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler() | ||
| 274 | -{ | ||
| 275 | -} | ||
| 276 | - | ||
| 277 | -int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 278 | -{ | ||
| 279 | - return srs_go_http_error(w, | ||
| 280 | - SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str); | ||
| 281 | -} | ||
| 282 | - | ||
| 283 | -SrsHttpFileServer::SrsHttpFileServer(string root_dir) | ||
| 284 | -{ | ||
| 285 | - dir = root_dir; | ||
| 286 | -} | ||
| 287 | - | ||
| 288 | -SrsHttpFileServer::~SrsHttpFileServer() | ||
| 289 | -{ | ||
| 290 | -} | ||
| 291 | - | ||
| 292 | -int SrsHttpFileServer::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 293 | -{ | ||
| 294 | - string upath = r->path(); | ||
| 295 | - | ||
| 296 | - // add default pages. | ||
| 297 | - if (srs_string_ends_with(upath, "/")) { | ||
| 298 | - upath += SRS_HTTP_DEFAULT_PAGE; | ||
| 299 | - } | ||
| 300 | - | ||
| 301 | - string fullpath = dir + "/"; | ||
| 302 | - | ||
| 303 | - // remove the virtual directory. | ||
| 304 | - srs_assert(entry); | ||
| 305 | - size_t pos = entry->pattern.find("/"); | ||
| 306 | - if (upath.length() > entry->pattern.length() && pos != string::npos) { | ||
| 307 | - fullpath += upath.substr(entry->pattern.length() - pos); | ||
| 308 | - } else { | ||
| 309 | - fullpath += upath; | ||
| 310 | - } | ||
| 311 | - | ||
| 312 | - // stat current dir, if exists, return error. | ||
| 313 | - if (!srs_path_exists(fullpath)) { | ||
| 314 | - srs_warn("http miss file=%s, pattern=%s, upath=%s", | ||
| 315 | - fullpath.c_str(), entry->pattern.c_str(), upath.c_str()); | ||
| 316 | - return SrsHttpNotFoundHandler().serve_http(w, r); | ||
| 317 | - } | ||
| 318 | - srs_trace("http match file=%s, pattern=%s, upath=%s", | ||
| 319 | - fullpath.c_str(), entry->pattern.c_str(), upath.c_str()); | ||
| 320 | - | ||
| 321 | - // handle file according to its extension. | ||
| 322 | - // use vod stream for .flv/.fhv | ||
| 323 | - if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) { | ||
| 324 | - return serve_flv_file(w, r, fullpath); | ||
| 325 | - } else if (srs_string_ends_with(fullpath, ".mp4")) { | ||
| 326 | - return serve_mp4_file(w, r, fullpath); | ||
| 327 | - } | ||
| 328 | - | ||
| 329 | - // serve common static file. | ||
| 330 | - return serve_file(w, r, fullpath); | ||
| 331 | -} | ||
| 332 | - | ||
| 333 | -int SrsHttpFileServer::serve_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) | ||
| 334 | -{ | ||
| 335 | - int ret = ERROR_SUCCESS; | ||
| 336 | - | ||
| 337 | - // open the target file. | ||
| 338 | - SrsFileReader fs; | ||
| 339 | - | ||
| 340 | - if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) { | ||
| 341 | - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret); | ||
| 342 | - return ret; | ||
| 343 | - } | ||
| 344 | - | ||
| 345 | - int64_t length = fs.filesize(); | ||
| 346 | - | ||
| 347 | - // unset the content length to encode in chunked encoding. | ||
| 348 | - w->header()->set_content_length(length); | ||
| 349 | - | ||
| 350 | - static std::map<std::string, std::string> _mime; | ||
| 351 | - if (_mime.empty()) { | ||
| 352 | - _mime[".ts"] = "video/MP2T"; | ||
| 353 | - _mime[".flv"] = "video/x-flv"; | ||
| 354 | - _mime[".m4v"] = "video/x-m4v"; | ||
| 355 | - _mime[".3gpp"] = "video/3gpp"; | ||
| 356 | - _mime[".3gp"] = "video/3gpp"; | ||
| 357 | - _mime[".mp4"] = "video/mp4"; | ||
| 358 | - _mime[".aac"] = "audio/x-aac"; | ||
| 359 | - _mime[".mp3"] = "audio/mpeg"; | ||
| 360 | - _mime[".m4a"] = "audio/x-m4a"; | ||
| 361 | - _mime[".ogg"] = "audio/ogg"; | ||
| 362 | - // @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 5. | ||
| 363 | - _mime[".m3u8"] = "application/vnd.apple.mpegurl"; // application/x-mpegURL | ||
| 364 | - _mime[".rss"] = "application/rss+xml"; | ||
| 365 | - _mime[".json"] = "application/json"; | ||
| 366 | - _mime[".swf"] = "application/x-shockwave-flash"; | ||
| 367 | - _mime[".doc"] = "application/msword"; | ||
| 368 | - _mime[".zip"] = "application/zip"; | ||
| 369 | - _mime[".rar"] = "application/x-rar-compressed"; | ||
| 370 | - _mime[".xml"] = "text/xml"; | ||
| 371 | - _mime[".html"] = "text/html"; | ||
| 372 | - _mime[".js"] = "text/javascript"; | ||
| 373 | - _mime[".css"] = "text/css"; | ||
| 374 | - _mime[".ico"] = "image/x-icon"; | ||
| 375 | - _mime[".png"] = "image/png"; | ||
| 376 | - _mime[".jpeg"] = "image/jpeg"; | ||
| 377 | - _mime[".jpg"] = "image/jpeg"; | ||
| 378 | - _mime[".gif"] = "image/gif"; | ||
| 379 | - } | ||
| 380 | - | ||
| 381 | - if (true) { | ||
| 382 | - size_t pos; | ||
| 383 | - std::string ext = fullpath; | ||
| 384 | - if ((pos = ext.rfind(".")) != string::npos) { | ||
| 385 | - ext = ext.substr(pos); | ||
| 386 | - } | ||
| 387 | - | ||
| 388 | - if (_mime.find(ext) == _mime.end()) { | ||
| 389 | - w->header()->set_content_type("application/octet-stream"); | ||
| 390 | - } else { | ||
| 391 | - w->header()->set_content_type(_mime[ext]); | ||
| 392 | - } | ||
| 393 | - } | ||
| 394 | - | ||
| 395 | - // write body. | ||
| 396 | - int64_t left = length; | ||
| 397 | - if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) { | ||
| 398 | - if (!srs_is_client_gracefully_close(ret)) { | ||
| 399 | - srs_error("read file=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret); | ||
| 400 | - } | ||
| 401 | - return ret; | ||
| 402 | - } | ||
| 403 | - | ||
| 404 | - return w->final_request(); | ||
| 405 | -} | ||
| 406 | - | ||
| 407 | -int SrsHttpFileServer::serve_flv_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) | ||
| 408 | -{ | ||
| 409 | - std::string start = r->query_get("start"); | ||
| 410 | - if (start.empty()) { | ||
| 411 | - return serve_file(w, r, fullpath); | ||
| 412 | - } | ||
| 413 | - | ||
| 414 | - int offset = ::atoi(start.c_str()); | ||
| 415 | - if (offset <= 0) { | ||
| 416 | - return serve_file(w, r, fullpath); | ||
| 417 | - } | ||
| 418 | - | ||
| 419 | - return serve_flv_stream(w, r, fullpath, offset); | ||
| 420 | -} | ||
| 421 | - | ||
| 422 | -int SrsHttpFileServer::serve_mp4_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath) | ||
| 423 | -{ | ||
| 424 | - // for flash to request mp4 range in query string. | ||
| 425 | - // for example, http://digitalprimates.net/dash/DashTest.html?url=http://dashdemo.edgesuite.net/digitalprimates/nexus/oops-20120802-manifest.mpd | ||
| 426 | - std::string range = r->query_get("range"); | ||
| 427 | - // or, use bytes to request range, | ||
| 428 | - // for example, http://dashas.castlabs.com/demo/try.html | ||
| 429 | - if (range.empty()) { | ||
| 430 | - range = r->query_get("bytes"); | ||
| 431 | - } | ||
| 432 | - | ||
| 433 | - // rollback to serve whole file. | ||
| 434 | - size_t pos = string::npos; | ||
| 435 | - if (range.empty() || (pos = range.find("-")) == string::npos) { | ||
| 436 | - return serve_file(w, r, fullpath); | ||
| 437 | - } | ||
| 438 | - | ||
| 439 | - // parse the start in query string | ||
| 440 | - int start = 0; | ||
| 441 | - if (pos > 0) { | ||
| 442 | - start = ::atoi(range.substr(0, pos).c_str()); | ||
| 443 | - } | ||
| 444 | - | ||
| 445 | - // parse end in query string. | ||
| 446 | - int end = -1; | ||
| 447 | - if (pos < range.length() - 1) { | ||
| 448 | - end = ::atoi(range.substr(pos + 1).c_str()); | ||
| 449 | - } | ||
| 450 | - | ||
| 451 | - // invalid param, serve as whole mp4 file. | ||
| 452 | - if (start < 0 || (end != -1 && start > end)) { | ||
| 453 | - return serve_file(w, r, fullpath); | ||
| 454 | - } | ||
| 455 | - | ||
| 456 | - return serve_mp4_stream(w, r, fullpath, start, end); | ||
| 457 | -} | ||
| 458 | - | ||
| 459 | -int SrsHttpFileServer::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) | ||
| 460 | -{ | ||
| 461 | - return serve_file(w, r, fullpath); | ||
| 462 | -} | ||
| 463 | - | ||
| 464 | -int SrsHttpFileServer::serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end) | ||
| 465 | -{ | ||
| 466 | - return serve_file(w, r, fullpath); | ||
| 467 | -} | ||
| 468 | - | ||
| 469 | -int SrsHttpFileServer::copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size) | ||
| 470 | -{ | ||
| 471 | - int ret = ERROR_SUCCESS; | ||
| 472 | - | ||
| 473 | - int left = size; | ||
| 474 | - char* buf = r->http_ts_send_buffer(); | ||
| 475 | - | ||
| 476 | - while (left > 0) { | ||
| 477 | - ssize_t nread = -1; | ||
| 478 | - int max_read = srs_min(left, SRS_HTTP_TS_SEND_BUFFER_SIZE); | ||
| 479 | - if ((ret = fs->read(buf, max_read, &nread)) != ERROR_SUCCESS) { | ||
| 480 | - break; | ||
| 481 | - } | ||
| 482 | - | ||
| 483 | - left -= nread; | ||
| 484 | - if ((ret = w->write(buf, (int)nread)) != ERROR_SUCCESS) { | ||
| 485 | - break; | ||
| 486 | - } | ||
| 487 | - } | ||
| 488 | - | ||
| 489 | - return ret; | ||
| 490 | -} | ||
| 491 | - | ||
| 492 | -SrsHttpMuxEntry::SrsHttpMuxEntry() | ||
| 493 | -{ | ||
| 494 | - enabled = true; | ||
| 495 | - explicit_match = false; | ||
| 496 | - handler = NULL; | ||
| 497 | -} | ||
| 498 | - | ||
| 499 | -SrsHttpMuxEntry::~SrsHttpMuxEntry() | ||
| 500 | -{ | ||
| 501 | - srs_freep(handler); | ||
| 502 | -} | ||
| 503 | - | ||
| 504 | -ISrsHttpMatchHijacker::ISrsHttpMatchHijacker() | ||
| 505 | -{ | ||
| 506 | -} | ||
| 507 | - | ||
| 508 | -ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker() | ||
| 509 | -{ | ||
| 510 | -} | ||
| 511 | - | ||
| 512 | -SrsHttpServeMux::SrsHttpServeMux() | ||
| 513 | -{ | ||
| 514 | -} | ||
| 515 | - | ||
| 516 | -SrsHttpServeMux::~SrsHttpServeMux() | ||
| 517 | -{ | ||
| 518 | - std::map<std::string, SrsHttpMuxEntry*>::iterator it; | ||
| 519 | - for (it = entries.begin(); it != entries.end(); ++it) { | ||
| 520 | - SrsHttpMuxEntry* entry = it->second; | ||
| 521 | - srs_freep(entry); | ||
| 522 | - } | ||
| 523 | - entries.clear(); | ||
| 524 | - | ||
| 525 | - vhosts.clear(); | ||
| 526 | - hijackers.clear(); | ||
| 527 | -} | ||
| 528 | - | ||
| 529 | -int SrsHttpServeMux::initialize() | ||
| 530 | -{ | ||
| 531 | - int ret = ERROR_SUCCESS; | ||
| 532 | - // TODO: FIXME: implements it. | ||
| 533 | - return ret; | ||
| 534 | -} | ||
| 535 | - | ||
| 536 | -void SrsHttpServeMux::hijack(ISrsHttpMatchHijacker* h) | ||
| 537 | -{ | ||
| 538 | - std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h); | ||
| 539 | - if (it != hijackers.end()) { | ||
| 540 | - return; | ||
| 541 | - } | ||
| 542 | - hijackers.push_back(h); | ||
| 543 | -} | ||
| 544 | - | ||
| 545 | -void SrsHttpServeMux::unhijack(ISrsHttpMatchHijacker* h) | ||
| 546 | -{ | ||
| 547 | - std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h); | ||
| 548 | - if (it == hijackers.end()) { | ||
| 549 | - return; | ||
| 550 | - } | ||
| 551 | - hijackers.erase(it); | ||
| 552 | -} | ||
| 553 | - | ||
| 554 | -int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler) | ||
| 555 | -{ | ||
| 556 | - int ret = ERROR_SUCCESS; | ||
| 557 | - | ||
| 558 | - srs_assert(handler); | ||
| 559 | - | ||
| 560 | - if (pattern.empty()) { | ||
| 561 | - ret = ERROR_HTTP_PATTERN_EMPTY; | ||
| 562 | - srs_error("http: empty pattern. ret=%d", ret); | ||
| 563 | - return ret; | ||
| 564 | - } | ||
| 565 | - | ||
| 566 | - if (entries.find(pattern) != entries.end()) { | ||
| 567 | - SrsHttpMuxEntry* exists = entries[pattern]; | ||
| 568 | - if (exists->explicit_match) { | ||
| 569 | - ret = ERROR_HTTP_PATTERN_DUPLICATED; | ||
| 570 | - srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret); | ||
| 571 | - return ret; | ||
| 572 | - } | ||
| 573 | - } | ||
| 574 | - | ||
| 575 | - std::string vhost = pattern; | ||
| 576 | - if (pattern.at(0) != '/') { | ||
| 577 | - if (pattern.find("/") != string::npos) { | ||
| 578 | - vhost = pattern.substr(0, pattern.find("/")); | ||
| 579 | - } | ||
| 580 | - vhosts[vhost] = handler; | ||
| 581 | - } | ||
| 582 | - | ||
| 583 | - if (true) { | ||
| 584 | - SrsHttpMuxEntry* entry = new SrsHttpMuxEntry(); | ||
| 585 | - entry->explicit_match = true; | ||
| 586 | - entry->handler = handler; | ||
| 587 | - entry->pattern = pattern; | ||
| 588 | - entry->handler->entry = entry; | ||
| 589 | - | ||
| 590 | - if (entries.find(pattern) != entries.end()) { | ||
| 591 | - SrsHttpMuxEntry* exists = entries[pattern]; | ||
| 592 | - srs_freep(exists); | ||
| 593 | - } | ||
| 594 | - entries[pattern] = entry; | ||
| 595 | - } | ||
| 596 | - | ||
| 597 | - // Helpful behavior: | ||
| 598 | - // If pattern is /tree/, insert an implicit permanent redirect for /tree. | ||
| 599 | - // It can be overridden by an explicit registration. | ||
| 600 | - if (pattern != "/" && !pattern.empty() && pattern.at(pattern.length() - 1) == '/') { | ||
| 601 | - std::string rpattern = pattern.substr(0, pattern.length() - 1); | ||
| 602 | - SrsHttpMuxEntry* entry = NULL; | ||
| 603 | - | ||
| 604 | - // free the exists not explicit entry | ||
| 605 | - if (entries.find(rpattern) != entries.end()) { | ||
| 606 | - SrsHttpMuxEntry* exists = entries[rpattern]; | ||
| 607 | - if (!exists->explicit_match) { | ||
| 608 | - entry = exists; | ||
| 609 | - } | ||
| 610 | - } | ||
| 611 | - | ||
| 612 | - // create implicit redirect. | ||
| 613 | - if (!entry || entry->explicit_match) { | ||
| 614 | - srs_freep(entry); | ||
| 615 | - | ||
| 616 | - entry = new SrsHttpMuxEntry(); | ||
| 617 | - entry->explicit_match = false; | ||
| 618 | - entry->handler = new SrsHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently); | ||
| 619 | - entry->pattern = pattern; | ||
| 620 | - entry->handler->entry = entry; | ||
| 621 | - | ||
| 622 | - entries[rpattern] = entry; | ||
| 623 | - } | ||
| 624 | - } | ||
| 625 | - | ||
| 626 | - return ret; | ||
| 627 | -} | ||
| 628 | - | ||
| 629 | -int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 630 | -{ | ||
| 631 | - int ret = ERROR_SUCCESS; | ||
| 632 | - | ||
| 633 | - ISrsHttpHandler* h = NULL; | ||
| 634 | - if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) { | ||
| 635 | - srs_error("find handler failed. ret=%d", ret); | ||
| 636 | - return ret; | ||
| 637 | - } | ||
| 638 | - | ||
| 639 | - srs_assert(h); | ||
| 640 | - if ((ret = h->serve_http(w, r)) != ERROR_SUCCESS) { | ||
| 641 | - if (!srs_is_client_gracefully_close(ret)) { | ||
| 642 | - srs_error("handler serve http failed. ret=%d", ret); | ||
| 643 | - } | ||
| 644 | - return ret; | ||
| 645 | - } | ||
| 646 | - | ||
| 647 | - return ret; | ||
| 648 | -} | ||
| 649 | - | ||
| 650 | -int SrsHttpServeMux::find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph) | ||
| 651 | -{ | ||
| 652 | - int ret = ERROR_SUCCESS; | ||
| 653 | - | ||
| 654 | - // TODO: FIXME: support the path . and .. | ||
| 655 | - if (r->url().find("..") != std::string::npos) { | ||
| 656 | - ret = ERROR_HTTP_URL_NOT_CLEAN; | ||
| 657 | - srs_error("htt url not canonical, url=%s. ret=%d", r->url().c_str(), ret); | ||
| 658 | - return ret; | ||
| 659 | - } | ||
| 660 | - | ||
| 661 | - if ((ret = match(r, ph)) != ERROR_SUCCESS) { | ||
| 662 | - srs_error("http match handler failed. ret=%d", ret); | ||
| 663 | - return ret; | ||
| 664 | - } | ||
| 665 | - | ||
| 666 | - // always hijack. | ||
| 667 | - if (!hijackers.empty()) { | ||
| 668 | - // notice all hijacker the match failed. | ||
| 669 | - std::vector<ISrsHttpMatchHijacker*>::iterator it; | ||
| 670 | - for (it = hijackers.begin(); it != hijackers.end(); ++it) { | ||
| 671 | - ISrsHttpMatchHijacker* hijacker = *it; | ||
| 672 | - if ((ret = hijacker->hijack(r, ph)) != ERROR_SUCCESS) { | ||
| 673 | - srs_error("hijacker match failed. ret=%d", ret); | ||
| 674 | - return ret; | ||
| 675 | - } | ||
| 676 | - } | ||
| 677 | - } | ||
| 678 | - | ||
| 679 | - if (*ph == NULL) { | ||
| 680 | - // TODO: FIXME: memory leak. | ||
| 681 | - *ph = new SrsHttpNotFoundHandler(); | ||
| 682 | - } | ||
| 683 | - | ||
| 684 | - return ret; | ||
| 685 | -} | ||
| 686 | - | ||
| 687 | -int SrsHttpServeMux::match(SrsHttpMessage* r, ISrsHttpHandler** ph) | ||
| 688 | -{ | ||
| 689 | - int ret = ERROR_SUCCESS; | ||
| 690 | - | ||
| 691 | - std::string path = r->path(); | ||
| 692 | - | ||
| 693 | - // Host-specific pattern takes precedence over generic ones | ||
| 694 | - if (!vhosts.empty() && vhosts.find(r->host()) != vhosts.end()) { | ||
| 695 | - path = r->host() + path; | ||
| 696 | - } | ||
| 697 | - | ||
| 698 | - int nb_matched = 0; | ||
| 699 | - ISrsHttpHandler* h = NULL; | ||
| 700 | - | ||
| 701 | - std::map<std::string, SrsHttpMuxEntry*>::iterator it; | ||
| 702 | - for (it = entries.begin(); it != entries.end(); ++it) { | ||
| 703 | - std::string pattern = it->first; | ||
| 704 | - SrsHttpMuxEntry* entry = it->second; | ||
| 705 | - | ||
| 706 | - if (!entry->enabled) { | ||
| 707 | - continue; | ||
| 708 | - } | ||
| 709 | - | ||
| 710 | - if (!path_match(pattern, path)) { | ||
| 711 | - continue; | ||
| 712 | - } | ||
| 713 | - | ||
| 714 | - if (!h || (int)pattern.length() > nb_matched) { | ||
| 715 | - nb_matched = (int)pattern.length(); | ||
| 716 | - h = entry->handler; | ||
| 717 | - } | ||
| 718 | - } | ||
| 719 | - | ||
| 720 | - *ph = h; | ||
| 721 | - | ||
| 722 | - return ret; | ||
| 723 | -} | ||
| 724 | - | ||
| 725 | -bool SrsHttpServeMux::path_match(string pattern, string path) | ||
| 726 | -{ | ||
| 727 | - if (pattern.empty()) { | ||
| 728 | - return false; | ||
| 729 | - } | ||
| 730 | - | ||
| 731 | - int n = (int)pattern.length(); | ||
| 732 | - | ||
| 733 | - // not endswith '/', exactly match. | ||
| 734 | - if (pattern.at(n - 1) != '/') { | ||
| 735 | - return pattern == path; | ||
| 736 | - } | ||
| 737 | - | ||
| 738 | - // endswith '/', match any, | ||
| 739 | - // for example, '/api/' match '/api/[N]' | ||
| 740 | - if ((int)path.length() >= n) { | ||
| 741 | - if (memcmp(pattern.data(), path.data(), n) == 0) { | ||
| 742 | - return true; | ||
| 743 | - } | ||
| 744 | - } | ||
| 745 | - | ||
| 746 | - return false; | ||
| 747 | -} | 38 | +#include <srs_core_autofree.hpp> |
| 748 | 39 | ||
| 749 | SrsHttpResponseWriter::SrsHttpResponseWriter(SrsStSocket* io) | 40 | SrsHttpResponseWriter::SrsHttpResponseWriter(SrsStSocket* io) |
| 750 | { | 41 | { |
| @@ -800,7 +91,7 @@ int SrsHttpResponseWriter::write(char* data, int size) | @@ -800,7 +91,7 @@ int SrsHttpResponseWriter::write(char* data, int size) | ||
| 800 | srs_error("http: send header failed. ret=%d", ret); | 91 | srs_error("http: send header failed. ret=%d", ret); |
| 801 | return ret; | 92 | return ret; |
| 802 | } | 93 | } |
| 803 | - | 94 | + |
| 804 | // ignore NULL content. | 95 | // ignore NULL content. |
| 805 | if (!data) { | 96 | if (!data) { |
| 806 | return ret; | 97 | return ret; |
| @@ -854,9 +145,9 @@ int SrsHttpResponseWriter::send_header(char* data, int size) | @@ -854,9 +145,9 @@ int SrsHttpResponseWriter::send_header(char* data, int size) | ||
| 854 | std::stringstream ss; | 145 | std::stringstream ss; |
| 855 | 146 | ||
| 856 | // status_line | 147 | // status_line |
| 857 | - ss << "HTTP/1.1 " << status << " " | ||
| 858 | - << srs_generate_http_status_text(status) << SRS_HTTP_CRLF; | ||
| 859 | - | 148 | + ss << "HTTP/1.1 " << status << " " |
| 149 | + << srs_generate_http_status_text(status) << SRS_HTTP_CRLF; | ||
| 150 | + | ||
| 860 | // detect content type | 151 | // detect content type |
| 861 | if (srs_go_http_body_allowd(status)) { | 152 | if (srs_go_http_body_allowd(status)) { |
| 862 | if (hdr->content_type().empty()) { | 153 | if (hdr->content_type().empty()) { |
| @@ -873,7 +164,7 @@ int SrsHttpResponseWriter::send_header(char* data, int size) | @@ -873,7 +164,7 @@ int SrsHttpResponseWriter::send_header(char* data, int size) | ||
| 873 | if (content_length == -1) { | 164 | if (content_length == -1) { |
| 874 | hdr->set("Transfer-Encoding", "chunked"); | 165 | hdr->set("Transfer-Encoding", "chunked"); |
| 875 | } | 166 | } |
| 876 | - | 167 | + |
| 877 | // keep alive to make vlc happy. | 168 | // keep alive to make vlc happy. |
| 878 | hdr->set("Connection", "Keep-Alive"); | 169 | hdr->set("Connection", "Keep-Alive"); |
| 879 | 170 | ||
| @@ -1036,7 +327,7 @@ int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read) | @@ -1036,7 +327,7 @@ int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read) | ||
| 1036 | return ret; | 327 | return ret; |
| 1037 | } | 328 | } |
| 1038 | buffer->read_slice(2); | 329 | buffer->read_slice(2); |
| 1039 | - | 330 | + |
| 1040 | return ret; | 331 | return ret; |
| 1041 | } | 332 | } |
| 1042 | 333 | ||
| @@ -1078,7 +369,7 @@ int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read) | @@ -1078,7 +369,7 @@ int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read) | ||
| 1078 | return ret; | 369 | return ret; |
| 1079 | } | 370 | } |
| 1080 | 371 | ||
| 1081 | -SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) | 372 | +SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) : ISrsHttpMessage() |
| 1082 | { | 373 | { |
| 1083 | conn = c; | 374 | conn = c; |
| 1084 | chunked = false; | 375 | chunked = false; |
| @@ -1098,11 +389,11 @@ SrsHttpMessage::~SrsHttpMessage() | @@ -1098,11 +389,11 @@ SrsHttpMessage::~SrsHttpMessage() | ||
| 1098 | int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, vector<SrsHttpHeaderField>& headers) | 389 | int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, vector<SrsHttpHeaderField>& headers) |
| 1099 | { | 390 | { |
| 1100 | int ret = ERROR_SUCCESS; | 391 | int ret = ERROR_SUCCESS; |
| 1101 | - | 392 | + |
| 1102 | _url = url; | 393 | _url = url; |
| 1103 | _header = *header; | 394 | _header = *header; |
| 1104 | _headers = headers; | 395 | _headers = headers; |
| 1105 | - | 396 | + |
| 1106 | // whether chunked. | 397 | // whether chunked. |
| 1107 | std::string transfer_encoding = get_request_header("Transfer-Encoding"); | 398 | std::string transfer_encoding = get_request_header("Transfer-Encoding"); |
| 1108 | chunked = (transfer_encoding == "chunked"); | 399 | chunked = (transfer_encoding == "chunked"); |
| @@ -1117,8 +408,8 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, | @@ -1117,8 +408,8 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, | ||
| 1117 | 408 | ||
| 1118 | // parse uri from url. | 409 | // parse uri from url. |
| 1119 | std::string host = get_request_header("Host"); | 410 | std::string host = get_request_header("Host"); |
| 1120 | - | ||
| 1121 | - // donot parse the empty host for uri, | 411 | + |
| 412 | + // donot parse the empty host for uri, | ||
| 1122 | // for example, the response contains no host, | 413 | // for example, the response contains no host, |
| 1123 | // ignore it is ok. | 414 | // ignore it is ok. |
| 1124 | if (host.empty()) { | 415 | if (host.empty()) { |
| @@ -1165,11 +456,6 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, | @@ -1165,11 +456,6 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, | ||
| 1165 | return ret; | 456 | return ret; |
| 1166 | } | 457 | } |
| 1167 | 458 | ||
| 1168 | -char* SrsHttpMessage::http_ts_send_buffer() | ||
| 1169 | -{ | ||
| 1170 | - return _http_ts_send_buffer; | ||
| 1171 | -} | ||
| 1172 | - | ||
| 1173 | SrsConnection* SrsHttpMessage::connection() | 459 | SrsConnection* SrsHttpMessage::connection() |
| 1174 | { | 460 | { |
| 1175 | return conn; | 461 | return conn; |
| @@ -1409,7 +695,7 @@ int SrsHttpParser::initialize(enum http_parser_type type) | @@ -1409,7 +695,7 @@ int SrsHttpParser::initialize(enum http_parser_type type) | ||
| 1409 | return ret; | 695 | return ret; |
| 1410 | } | 696 | } |
| 1411 | 697 | ||
| 1412 | -int SrsHttpParser::parse_message(SrsStSocket* skt, SrsConnection* conn, SrsHttpMessage** ppmsg) | 698 | +int SrsHttpParser::parse_message(SrsStSocket* skt, SrsConnection* conn, ISrsHttpMessage** ppmsg) |
| 1413 | { | 699 | { |
| 1414 | *ppmsg = NULL; | 700 | *ppmsg = NULL; |
| 1415 | 701 |
| @@ -34,366 +34,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -34,366 +34,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 34 | #include <map> | 34 | #include <map> |
| 35 | #include <string> | 35 | #include <string> |
| 36 | #include <vector> | 36 | #include <vector> |
| 37 | -#include <sstream> | ||
| 38 | 37 | ||
| 39 | #include <http_parser.h> | 38 | #include <http_parser.h> |
| 40 | 39 | ||
| 41 | #include <srs_app_st.hpp> | 40 | #include <srs_app_st.hpp> |
| 42 | -#include <srs_kernel_consts.hpp> | ||
| 43 | #include <srs_http_stack.hpp> | 41 | #include <srs_http_stack.hpp> |
| 44 | 42 | ||
| 45 | class SrsRequest; | 43 | class SrsRequest; |
| 46 | class SrsStSocket; | 44 | class SrsStSocket; |
| 47 | -class SrsHttpUri; | ||
| 48 | class SrsHttpMessage; | 45 | class SrsHttpMessage; |
| 49 | -class SrsFileReader; | ||
| 50 | -class SrsSimpleBuffer; | ||
| 51 | -class SrsHttpMuxEntry; | ||
| 52 | -class ISrsHttpResponseWriter; | ||
| 53 | class SrsFastBuffer; | 46 | class SrsFastBuffer; |
| 47 | +class SrsHttpUri; | ||
| 54 | class SrsConnection; | 48 | class SrsConnection; |
| 55 | 49 | ||
| 56 | -// http specification | ||
| 57 | -// CR = <US-ASCII CR, carriage return (13)> | ||
| 58 | -#define SRS_HTTP_CR SRS_CONSTS_CR // 0x0D | ||
| 59 | -// LF = <US-ASCII LF, linefeed (10)> | ||
| 60 | -#define SRS_HTTP_LF SRS_CONSTS_LF // 0x0A | ||
| 61 | -// SP = <US-ASCII SP, space (32)> | ||
| 62 | -#define SRS_HTTP_SP ' ' // 0x20 | ||
| 63 | -// HT = <US-ASCII HT, horizontal-tab (9)> | ||
| 64 | -#define SRS_HTTP_HT '\x09' // 0x09 | ||
| 65 | - | ||
| 66 | -// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all | ||
| 67 | -// protocol elements except the entity-body (see appendix 19.3 for | ||
| 68 | -// tolerant applications). | ||
| 69 | -#define SRS_HTTP_CRLF "\r\n" // 0x0D0A | ||
| 70 | -#define SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A | ||
| 71 | - | ||
| 72 | -// @see SrsHttpMessage._http_ts_send_buffer | ||
| 73 | -#define SRS_HTTP_TS_SEND_BUFFER_SIZE 4096 | ||
| 74 | - | ||
| 75 | -// helper function: response in json format. | ||
| 76 | -extern int srs_http_response_json(ISrsHttpResponseWriter* w, std::string data); | ||
| 77 | - | ||
| 78 | -// state of message | ||
| 79 | -enum SrsHttpParseState { | ||
| 80 | - SrsHttpParseStateInit = 0, | ||
| 81 | - SrsHttpParseStateStart, | ||
| 82 | - SrsHttpParseStateHeaderComplete, | ||
| 83 | - SrsHttpParseStateMessageComplete | ||
| 84 | -}; | ||
| 85 | - | ||
| 86 | -// A Header represents the key-value pairs in an HTTP header. | ||
| 87 | -class SrsHttpHeader | ||
| 88 | -{ | ||
| 89 | -private: | ||
| 90 | - std::map<std::string, std::string> headers; | ||
| 91 | -public: | ||
| 92 | - SrsHttpHeader(); | ||
| 93 | - virtual ~SrsHttpHeader(); | ||
| 94 | -public: | ||
| 95 | - // Add adds the key, value pair to the header. | ||
| 96 | - // It appends to any existing values associated with key. | ||
| 97 | - virtual void set(std::string key, std::string value); | ||
| 98 | - // Get gets the first value associated with the given key. | ||
| 99 | - // If there are no values associated with the key, Get returns "". | ||
| 100 | - // To access multiple values of a key, access the map directly | ||
| 101 | - // with CanonicalHeaderKey. | ||
| 102 | - virtual std::string get(std::string key); | ||
| 103 | -public: | ||
| 104 | - /** | ||
| 105 | - * get the content length. -1 if not set. | ||
| 106 | - */ | ||
| 107 | - virtual int64_t content_length(); | ||
| 108 | - /** | ||
| 109 | - * set the content length by header "Content-Length" | ||
| 110 | - */ | ||
| 111 | - virtual void set_content_length(int64_t size); | ||
| 112 | -public: | ||
| 113 | - /** | ||
| 114 | - * get the content type. empty string if not set. | ||
| 115 | - */ | ||
| 116 | - virtual std::string content_type(); | ||
| 117 | - /** | ||
| 118 | - * set the content type by header "Content-Type" | ||
| 119 | - */ | ||
| 120 | - virtual void set_content_type(std::string ct); | ||
| 121 | -public: | ||
| 122 | - /** | ||
| 123 | - * write all headers to string stream. | ||
| 124 | - */ | ||
| 125 | - virtual void write(std::stringstream& ss); | ||
| 126 | -}; | ||
| 127 | - | ||
| 128 | -// A ResponseWriter interface is used by an HTTP handler to | ||
| 129 | -// construct an HTTP response. | ||
| 130 | -// Usage 1, response with specified length content: | ||
| 131 | -// ISrsHttpResponseWriter* w; // create or get response. | ||
| 132 | -// std::string msg = "Hello, HTTP!"; | ||
| 133 | -// w->header()->set_content_type("text/plain; charset=utf-8"); | ||
| 134 | -// w->header()->set_content_length(msg.length()); | ||
| 135 | -// w->write_header(SRS_CONSTS_HTTP_OK); | ||
| 136 | -// w->write((char*)msg.data(), (int)msg.length()); | ||
| 137 | -// w->final_request(); // optional flush. | ||
| 138 | -// Usage 2, response with HTTP code only, zero content length. | ||
| 139 | -// ISrsHttpResponseWriter* w; // create or get response. | ||
| 140 | -// w->header()->set_content_length(0); | ||
| 141 | -// w->write_header(SRS_CONSTS_HTTP_OK); | ||
| 142 | -// w->final_request(); | ||
| 143 | -// Usage 3, response in chunked encoding. | ||
| 144 | -// ISrsHttpResponseWriter* w; // create or get response. | ||
| 145 | -// std::string msg = "Hello, HTTP!"; | ||
| 146 | -// w->header()->set_content_type("application/octet-stream"); | ||
| 147 | -// w->write_header(SRS_CONSTS_HTTP_OK); | ||
| 148 | -// w->write((char*)msg.data(), (int)msg.length()); | ||
| 149 | -// w->write((char*)msg.data(), (int)msg.length()); | ||
| 150 | -// w->write((char*)msg.data(), (int)msg.length()); | ||
| 151 | -// w->write((char*)msg.data(), (int)msg.length()); | ||
| 152 | -// w->final_request(); // required to end the chunked and flush. | ||
| 153 | -class ISrsHttpResponseWriter | ||
| 154 | -{ | ||
| 155 | -public: | ||
| 156 | - ISrsHttpResponseWriter(); | ||
| 157 | - virtual ~ISrsHttpResponseWriter(); | ||
| 158 | -public: | ||
| 159 | - // when chunked mode, | ||
| 160 | - // final the request to complete the chunked encoding. | ||
| 161 | - // for no-chunked mode, | ||
| 162 | - // final to send request, for example, content-length is 0. | ||
| 163 | - virtual int final_request() = 0; | ||
| 164 | - | ||
| 165 | - // Header returns the header map that will be sent by WriteHeader. | ||
| 166 | - // Changing the header after a call to WriteHeader (or Write) has | ||
| 167 | - // no effect. | ||
| 168 | - virtual SrsHttpHeader* header() = 0; | ||
| 169 | - | ||
| 170 | - // Write writes the data to the connection as part of an HTTP reply. | ||
| 171 | - // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK) | ||
| 172 | - // before writing the data. If the Header does not contain a | ||
| 173 | - // Content-Type line, Write adds a Content-Type set to the result of passing | ||
| 174 | - // the initial 512 bytes of written data to DetectContentType. | ||
| 175 | - // @param data, the data to send. NULL to flush header only. | ||
| 176 | - virtual int write(char* data, int size) = 0; | ||
| 177 | - | ||
| 178 | - // WriteHeader sends an HTTP response header with status code. | ||
| 179 | - // If WriteHeader is not called explicitly, the first call to Write | ||
| 180 | - // will trigger an implicit WriteHeader(http.StatusOK). | ||
| 181 | - // Thus explicit calls to WriteHeader are mainly used to | ||
| 182 | - // send error codes. | ||
| 183 | - // @remark, user must set header then write or write_header. | ||
| 184 | - virtual void write_header(int code) = 0; | ||
| 185 | -}; | ||
| 186 | - | ||
| 187 | /** | 50 | /** |
| 188 | -* the reader interface for http response. | ||
| 189 | -*/ | ||
| 190 | -class ISrsHttpResponseReader | ||
| 191 | -{ | ||
| 192 | -public: | ||
| 193 | - ISrsHttpResponseReader(); | ||
| 194 | - virtual ~ISrsHttpResponseReader(); | ||
| 195 | -public: | ||
| 196 | - /** | ||
| 197 | - * whether response read EOF. | ||
| 198 | - */ | ||
| 199 | - virtual bool eof() = 0; | ||
| 200 | - /** | ||
| 201 | - * read from the response body. | ||
| 202 | - * @param data, the buffer to read data buffer to. | ||
| 203 | - * @param nb_data, the max size of data buffer. | ||
| 204 | - * @param nb_read, the actual read size of bytes. NULL to ignore. | ||
| 205 | - * @remark when eof(), return error. | ||
| 206 | - */ | ||
| 207 | - virtual int read(char* data, int nb_data, int* nb_read) = 0; | ||
| 208 | -}; | ||
| 209 | - | ||
| 210 | -// Objects implementing the Handler interface can be | ||
| 211 | -// registered to serve a particular path or subtree | ||
| 212 | -// in the HTTP server. | ||
| 213 | -// | ||
| 214 | -// ServeHTTP should write reply headers and data to the ResponseWriter | ||
| 215 | -// and then return. Returning signals that the request is finished | ||
| 216 | -// and that the HTTP server can move on to the next request on | ||
| 217 | -// the connection. | ||
| 218 | -class ISrsHttpHandler | ||
| 219 | -{ | ||
| 220 | -public: | ||
| 221 | - SrsHttpMuxEntry* entry; | ||
| 222 | -public: | ||
| 223 | - ISrsHttpHandler(); | ||
| 224 | - virtual ~ISrsHttpHandler(); | ||
| 225 | -public: | ||
| 226 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) = 0; | ||
| 227 | -}; | ||
| 228 | - | ||
| 229 | -// Redirect to a fixed URL | ||
| 230 | -class SrsHttpRedirectHandler : public ISrsHttpHandler | ||
| 231 | -{ | ||
| 232 | -private: | ||
| 233 | - std::string url; | ||
| 234 | - int code; | ||
| 235 | -public: | ||
| 236 | - SrsHttpRedirectHandler(std::string u, int c); | ||
| 237 | - virtual ~SrsHttpRedirectHandler(); | ||
| 238 | -public: | ||
| 239 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 240 | -}; | ||
| 241 | - | ||
| 242 | -// NotFound replies to the request with an HTTP 404 not found error. | ||
| 243 | -class SrsHttpNotFoundHandler : public ISrsHttpHandler | ||
| 244 | -{ | ||
| 245 | -public: | ||
| 246 | - SrsHttpNotFoundHandler(); | ||
| 247 | - virtual ~SrsHttpNotFoundHandler(); | ||
| 248 | -public: | ||
| 249 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 250 | -}; | ||
| 251 | - | ||
| 252 | -// FileServer returns a handler that serves HTTP requests | ||
| 253 | -// with the contents of the file system rooted at root. | ||
| 254 | -// | ||
| 255 | -// To use the operating system's file system implementation, | ||
| 256 | -// use http.Dir: | ||
| 257 | -// | ||
| 258 | -// http.Handle("/", SrsHttpFileServer("/tmp")) | ||
| 259 | -// http.Handle("/", SrsHttpFileServer("static-dir")) | ||
| 260 | -class SrsHttpFileServer : public ISrsHttpHandler | ||
| 261 | -{ | ||
| 262 | -protected: | ||
| 263 | - std::string dir; | ||
| 264 | -public: | ||
| 265 | - SrsHttpFileServer(std::string root_dir); | ||
| 266 | - virtual ~SrsHttpFileServer(); | ||
| 267 | -public: | ||
| 268 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 269 | -private: | ||
| 270 | - /** | ||
| 271 | - * serve the file by specified path | ||
| 272 | - */ | ||
| 273 | - virtual int serve_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); | ||
| 274 | - virtual int serve_flv_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); | ||
| 275 | - virtual int serve_mp4_file(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath); | ||
| 276 | -protected: | ||
| 277 | - /** | ||
| 278 | - * when access flv file with x.flv?start=xxx | ||
| 279 | - */ | ||
| 280 | - virtual int serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); | ||
| 281 | - /** | ||
| 282 | - * when access mp4 file with x.mp4?range=start-end | ||
| 283 | - * @param start the start offset in bytes. | ||
| 284 | - * @param end the end offset in bytes. -1 to end of file. | ||
| 285 | - * @remark response data in [start, end]. | ||
| 286 | - */ | ||
| 287 | - virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end); | ||
| 288 | -protected: | ||
| 289 | - /** | ||
| 290 | - * copy the fs to response writer in size bytes. | ||
| 291 | - */ | ||
| 292 | - virtual int copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, SrsHttpMessage* r, int size); | ||
| 293 | -}; | ||
| 294 | - | ||
| 295 | -// the mux entry for server mux. | ||
| 296 | -// the matcher info, for example, the pattern and handler. | ||
| 297 | -class SrsHttpMuxEntry | ||
| 298 | -{ | ||
| 299 | -public: | ||
| 300 | - bool explicit_match; | ||
| 301 | - ISrsHttpHandler* handler; | ||
| 302 | - std::string pattern; | ||
| 303 | - bool enabled; | ||
| 304 | -public: | ||
| 305 | - SrsHttpMuxEntry(); | ||
| 306 | - virtual ~SrsHttpMuxEntry(); | ||
| 307 | -}; | ||
| 308 | - | ||
| 309 | -/** | ||
| 310 | -* the hijacker for http pattern match. | ||
| 311 | -*/ | ||
| 312 | -class ISrsHttpMatchHijacker | ||
| 313 | -{ | ||
| 314 | -public: | ||
| 315 | - ISrsHttpMatchHijacker(); | ||
| 316 | - virtual ~ISrsHttpMatchHijacker(); | ||
| 317 | -public: | ||
| 318 | - /** | ||
| 319 | - * when match the request failed, no handler to process request. | ||
| 320 | - * @param request the http request message to match the handler. | ||
| 321 | - * @param ph the already matched handler, hijack can rewrite it. | ||
| 322 | - */ | ||
| 323 | - virtual int hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) = 0; | ||
| 324 | -}; | ||
| 325 | - | ||
| 326 | -// ServeMux is an HTTP request multiplexer. | ||
| 327 | -// It matches the URL of each incoming request against a list of registered | ||
| 328 | -// patterns and calls the handler for the pattern that | ||
| 329 | -// most closely matches the URL. | ||
| 330 | -// | ||
| 331 | -// Patterns name fixed, rooted paths, like "/favicon.ico", | ||
| 332 | -// or rooted subtrees, like "/images/" (note the trailing slash). | ||
| 333 | -// Longer patterns take precedence over shorter ones, so that | ||
| 334 | -// if there are handlers registered for both "/images/" | ||
| 335 | -// and "/images/thumbnails/", the latter handler will be | ||
| 336 | -// called for paths beginning "/images/thumbnails/" and the | ||
| 337 | -// former will receive requests for any other paths in the | ||
| 338 | -// "/images/" subtree. | ||
| 339 | -// | ||
| 340 | -// Note that since a pattern ending in a slash names a rooted subtree, | ||
| 341 | -// the pattern "/" matches all paths not matched by other registered | ||
| 342 | -// patterns, not just the URL with Path == "/". | ||
| 343 | -// | ||
| 344 | -// Patterns may optionally begin with a host name, restricting matches to | ||
| 345 | -// URLs on that host only. Host-specific patterns take precedence over | ||
| 346 | -// general patterns, so that a handler might register for the two patterns | ||
| 347 | -// "/codesearch" and "codesearch.google.com/" without also taking over | ||
| 348 | -// requests for "http://www.google.com/". | ||
| 349 | -// | ||
| 350 | -// ServeMux also takes care of sanitizing the URL request path, | ||
| 351 | -// redirecting any request containing . or .. elements to an | ||
| 352 | -// equivalent .- and ..-free URL. | ||
| 353 | -class SrsHttpServeMux | ||
| 354 | -{ | ||
| 355 | -private: | ||
| 356 | - // the pattern handler, to handle the http request. | ||
| 357 | - std::map<std::string, SrsHttpMuxEntry*> entries; | ||
| 358 | - // the vhost handler. | ||
| 359 | - // when find the handler to process the request, | ||
| 360 | - // append the matched vhost when pattern not starts with /, | ||
| 361 | - // for example, for pattern /live/livestream.flv of vhost ossrs.net, | ||
| 362 | - // the path will rewrite to ossrs.net/live/livestream.flv | ||
| 363 | - std::map<std::string, ISrsHttpHandler*> vhosts; | ||
| 364 | - // all hijackers for http match. | ||
| 365 | - // for example, the hstrs(http stream trigger rtmp source) | ||
| 366 | - // can hijack and install handler when request incoming and no handler. | ||
| 367 | - std::vector<ISrsHttpMatchHijacker*> hijackers; | ||
| 368 | -public: | ||
| 369 | - SrsHttpServeMux(); | ||
| 370 | - virtual ~SrsHttpServeMux(); | ||
| 371 | -public: | ||
| 372 | - /** | ||
| 373 | - * initialize the http serve mux. | ||
| 374 | - */ | ||
| 375 | - virtual int initialize(); | ||
| 376 | - /** | ||
| 377 | - * hijack the http match. | ||
| 378 | - */ | ||
| 379 | - virtual void hijack(ISrsHttpMatchHijacker* h); | ||
| 380 | - virtual void unhijack(ISrsHttpMatchHijacker* h); | ||
| 381 | -public: | ||
| 382 | - // Handle registers the handler for the given pattern. | ||
| 383 | - // If a handler already exists for pattern, Handle panics. | ||
| 384 | - virtual int handle(std::string pattern, ISrsHttpHandler* handler); | ||
| 385 | -// interface ISrsHttpHandler | ||
| 386 | -public: | ||
| 387 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 388 | -private: | ||
| 389 | - virtual int find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph); | ||
| 390 | - virtual int match(SrsHttpMessage* r, ISrsHttpHandler** ph); | ||
| 391 | - virtual bool path_match(std::string pattern, std::string path); | ||
| 392 | -}; | ||
| 393 | - | ||
| 394 | -/** | ||
| 395 | -* response writer use st socket | ||
| 396 | -*/ | 51 | + * response writer use st socket |
| 52 | + */ | ||
| 397 | class SrsHttpResponseWriter : public ISrsHttpResponseWriter | 53 | class SrsHttpResponseWriter : public ISrsHttpResponseWriter |
| 398 | { | 54 | { |
| 399 | private: | 55 | private: |
| @@ -402,7 +58,7 @@ private: | @@ -402,7 +58,7 @@ private: | ||
| 402 | private: | 58 | private: |
| 403 | // reply header has been (logically) written | 59 | // reply header has been (logically) written |
| 404 | bool header_wrote; | 60 | bool header_wrote; |
| 405 | - // status code passed to WriteHeader | 61 | + // status code passed to WriteHeader |
| 406 | int status; | 62 | int status; |
| 407 | private: | 63 | private: |
| 408 | // explicitly-declared Content-Length; or -1 | 64 | // explicitly-declared Content-Length; or -1 |
| @@ -427,8 +83,8 @@ public: | @@ -427,8 +83,8 @@ public: | ||
| 427 | }; | 83 | }; |
| 428 | 84 | ||
| 429 | /** | 85 | /** |
| 430 | -* response reader use st socket. | ||
| 431 | -*/ | 86 | + * response reader use st socket. |
| 87 | + */ | ||
| 432 | class SrsHttpResponseReader : virtual public ISrsHttpResponseReader | 88 | class SrsHttpResponseReader : virtual public ISrsHttpResponseReader |
| 433 | { | 89 | { |
| 434 | private: | 90 | private: |
| @@ -447,10 +103,10 @@ public: | @@ -447,10 +103,10 @@ public: | ||
| 447 | virtual ~SrsHttpResponseReader(); | 103 | virtual ~SrsHttpResponseReader(); |
| 448 | public: | 104 | public: |
| 449 | /** | 105 | /** |
| 450 | - * initialize the response reader with buffer. | ||
| 451 | - */ | 106 | + * initialize the response reader with buffer. |
| 107 | + */ | ||
| 452 | virtual int initialize(SrsFastBuffer* buffer); | 108 | virtual int initialize(SrsFastBuffer* buffer); |
| 453 | -// interface ISrsHttpResponseReader | 109 | + // interface ISrsHttpResponseReader |
| 454 | public: | 110 | public: |
| 455 | virtual bool eof(); | 111 | virtual bool eof(); |
| 456 | virtual int read(char* data, int nb_data, int* nb_read); | 112 | virtual int read(char* data, int nb_data, int* nb_read); |
| @@ -469,31 +125,31 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField; | @@ -469,31 +125,31 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField; | ||
| 469 | // usage. In addition to the notes on the fields below, see the | 125 | // usage. In addition to the notes on the fields below, see the |
| 470 | // documentation for Request.Write and RoundTripper. | 126 | // documentation for Request.Write and RoundTripper. |
| 471 | /** | 127 | /** |
| 472 | -* the http message, request or response. | ||
| 473 | -*/ | ||
| 474 | -class SrsHttpMessage | 128 | + * the http message, request or response. |
| 129 | + */ | ||
| 130 | +class SrsHttpMessage : public ISrsHttpMessage | ||
| 475 | { | 131 | { |
| 476 | private: | 132 | private: |
| 477 | /** | 133 | /** |
| 478 | - * parsed url. | ||
| 479 | - */ | 134 | + * parsed url. |
| 135 | + */ | ||
| 480 | std::string _url; | 136 | std::string _url; |
| 481 | /** | 137 | /** |
| 482 | - * the extension of file, for example, .flv | ||
| 483 | - */ | 138 | + * the extension of file, for example, .flv |
| 139 | + */ | ||
| 484 | std::string _ext; | 140 | std::string _ext; |
| 485 | /** | 141 | /** |
| 486 | - * parsed http header. | ||
| 487 | - */ | 142 | + * parsed http header. |
| 143 | + */ | ||
| 488 | http_parser _header; | 144 | http_parser _header; |
| 489 | /** | 145 | /** |
| 490 | - * body object, reader object. | ||
| 491 | - * @remark, user can get body in string by get_body(). | ||
| 492 | - */ | 146 | + * body object, reader object. |
| 147 | + * @remark, user can get body in string by get_body(). | ||
| 148 | + */ | ||
| 493 | SrsHttpResponseReader* _body; | 149 | SrsHttpResponseReader* _body; |
| 494 | /** | 150 | /** |
| 495 | - * whether the body is chunked. | ||
| 496 | - */ | 151 | + * whether the body is chunked. |
| 152 | + */ | ||
| 497 | bool chunked; | 153 | bool chunked; |
| 498 | /** | 154 | /** |
| 499 | * whether the request indicates should keep alive | 155 | * whether the request indicates should keep alive |
| @@ -501,12 +157,12 @@ private: | @@ -501,12 +157,12 @@ private: | ||
| 501 | */ | 157 | */ |
| 502 | bool keep_alive; | 158 | bool keep_alive; |
| 503 | /** | 159 | /** |
| 504 | - * uri parser | ||
| 505 | - */ | 160 | + * uri parser |
| 161 | + */ | ||
| 506 | SrsHttpUri* _uri; | 162 | SrsHttpUri* _uri; |
| 507 | /** | 163 | /** |
| 508 | - * use a buffer to read and send ts file. | ||
| 509 | - */ | 164 | + * use a buffer to read and send ts file. |
| 165 | + */ | ||
| 510 | // TODO: FIXME: remove it. | 166 | // TODO: FIXME: remove it. |
| 511 | char* _http_ts_send_buffer; | 167 | char* _http_ts_send_buffer; |
| 512 | // http headers | 168 | // http headers |
| @@ -520,20 +176,19 @@ public: | @@ -520,20 +176,19 @@ public: | ||
| 520 | virtual ~SrsHttpMessage(); | 176 | virtual ~SrsHttpMessage(); |
| 521 | public: | 177 | public: |
| 522 | /** | 178 | /** |
| 523 | - * set the original messages, then update the message. | ||
| 524 | - */ | ||
| 525 | - virtual int update(std::string url, http_parser* header, | 179 | + * set the original messages, then update the message. |
| 180 | + */ | ||
| 181 | + virtual int update(std::string url, http_parser* header, | ||
| 526 | SrsFastBuffer* body, std::vector<SrsHttpHeaderField>& headers | 182 | SrsFastBuffer* body, std::vector<SrsHttpHeaderField>& headers |
| 527 | ); | 183 | ); |
| 528 | -public: | ||
| 529 | - virtual char* http_ts_send_buffer(); | 184 | +private: |
| 530 | virtual SrsConnection* connection(); | 185 | virtual SrsConnection* connection(); |
| 531 | public: | 186 | public: |
| 532 | virtual u_int8_t method(); | 187 | virtual u_int8_t method(); |
| 533 | virtual u_int16_t status_code(); | 188 | virtual u_int16_t status_code(); |
| 534 | /** | 189 | /** |
| 535 | - * method helpers. | ||
| 536 | - */ | 190 | + * method helpers. |
| 191 | + */ | ||
| 537 | virtual std::string method_str(); | 192 | virtual std::string method_str(); |
| 538 | virtual bool is_http_get(); | 193 | virtual bool is_http_get(); |
| 539 | virtual bool is_http_put(); | 194 | virtual bool is_http_put(); |
| @@ -541,57 +196,57 @@ public: | @@ -541,57 +196,57 @@ public: | ||
| 541 | virtual bool is_http_delete(); | 196 | virtual bool is_http_delete(); |
| 542 | virtual bool is_http_options(); | 197 | virtual bool is_http_options(); |
| 543 | /** | 198 | /** |
| 544 | - * whether body is chunked encoding, for reader only. | ||
| 545 | - */ | 199 | + * whether body is chunked encoding, for reader only. |
| 200 | + */ | ||
| 546 | virtual bool is_chunked(); | 201 | virtual bool is_chunked(); |
| 547 | /** | 202 | /** |
| 548 | * whether should keep the connection alive. | 203 | * whether should keep the connection alive. |
| 549 | */ | 204 | */ |
| 550 | virtual bool is_keep_alive(); | 205 | virtual bool is_keep_alive(); |
| 551 | /** | 206 | /** |
| 552 | - * the uri contains the host and path. | ||
| 553 | - */ | 207 | + * the uri contains the host and path. |
| 208 | + */ | ||
| 554 | virtual std::string uri(); | 209 | virtual std::string uri(); |
| 555 | /** | 210 | /** |
| 556 | - * the url maybe the path. | ||
| 557 | - */ | 211 | + * the url maybe the path. |
| 212 | + */ | ||
| 558 | virtual std::string url(); | 213 | virtual std::string url(); |
| 559 | virtual std::string host(); | 214 | virtual std::string host(); |
| 560 | virtual std::string path(); | 215 | virtual std::string path(); |
| 561 | virtual std::string ext(); | 216 | virtual std::string ext(); |
| 562 | public: | 217 | public: |
| 563 | /** | 218 | /** |
| 564 | - * read body to string. | ||
| 565 | - * @remark for small http body. | ||
| 566 | - */ | 219 | + * read body to string. |
| 220 | + * @remark for small http body. | ||
| 221 | + */ | ||
| 567 | virtual int body_read_all(std::string& body); | 222 | virtual int body_read_all(std::string& body); |
| 568 | /** | 223 | /** |
| 569 | - * get the body reader, to read one by one. | ||
| 570 | - * @remark when body is very large, or chunked, use this. | ||
| 571 | - */ | 224 | + * get the body reader, to read one by one. |
| 225 | + * @remark when body is very large, or chunked, use this. | ||
| 226 | + */ | ||
| 572 | virtual ISrsHttpResponseReader* body_reader(); | 227 | virtual ISrsHttpResponseReader* body_reader(); |
| 573 | /** | 228 | /** |
| 574 | - * the content length, -1 for chunked or not set. | ||
| 575 | - */ | 229 | + * the content length, -1 for chunked or not set. |
| 230 | + */ | ||
| 576 | virtual int64_t content_length(); | 231 | virtual int64_t content_length(); |
| 577 | /** | 232 | /** |
| 578 | - * get the param in query string, | ||
| 579 | - * for instance, query is "start=100&end=200", | ||
| 580 | - * then query_get("start") is "100", and query_get("end") is "200" | ||
| 581 | - */ | 233 | + * get the param in query string, |
| 234 | + * for instance, query is "start=100&end=200", | ||
| 235 | + * then query_get("start") is "100", and query_get("end") is "200" | ||
| 236 | + */ | ||
| 582 | virtual std::string query_get(std::string key); | 237 | virtual std::string query_get(std::string key); |
| 583 | /** | 238 | /** |
| 584 | - * get the headers. | ||
| 585 | - */ | 239 | + * get the headers. |
| 240 | + */ | ||
| 586 | virtual int request_header_count(); | 241 | virtual int request_header_count(); |
| 587 | virtual std::string request_header_key_at(int index); | 242 | virtual std::string request_header_key_at(int index); |
| 588 | virtual std::string request_header_value_at(int index); | 243 | virtual std::string request_header_value_at(int index); |
| 589 | virtual std::string get_request_header(std::string name); | 244 | virtual std::string get_request_header(std::string name); |
| 590 | public: | 245 | public: |
| 591 | /** | 246 | /** |
| 592 | - * convert the http message to a request. | ||
| 593 | - * @remark user must free the return request. | ||
| 594 | - */ | 247 | + * convert the http message to a request. |
| 248 | + * @remark user must free the return request. | ||
| 249 | + */ | ||
| 595 | virtual SrsRequest* to_request(std::string vhost); | 250 | virtual SrsRequest* to_request(std::string vhost); |
| 596 | }; | 251 | }; |
| 597 | 252 | ||
| @@ -631,7 +286,7 @@ public: | @@ -631,7 +286,7 @@ public: | ||
| 631 | * or error and *ppmsg must be NULL. | 286 | * or error and *ppmsg must be NULL. |
| 632 | * @remark, if success, *ppmsg always NOT-NULL, *ppmsg always is_complete(). | 287 | * @remark, if success, *ppmsg always NOT-NULL, *ppmsg always is_complete(). |
| 633 | */ | 288 | */ |
| 634 | - virtual int parse_message(SrsStSocket* skt, SrsConnection* conn, SrsHttpMessage** ppmsg); | 289 | + virtual int parse_message(SrsStSocket* skt, SrsConnection* conn, ISrsHttpMessage** ppmsg); |
| 635 | private: | 290 | private: |
| 636 | /** | 291 | /** |
| 637 | * parse the HTTP message to member field: msg. | 292 | * parse the HTTP message to member field: msg. |
| @@ -48,7 +48,7 @@ SrsGoApiRoot::~SrsGoApiRoot() | @@ -48,7 +48,7 @@ SrsGoApiRoot::~SrsGoApiRoot() | ||
| 48 | { | 48 | { |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | -int SrsGoApiRoot::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 51 | +int SrsGoApiRoot::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 52 | { | 52 | { |
| 53 | std::stringstream ss; | 53 | std::stringstream ss; |
| 54 | 54 | ||
| @@ -70,7 +70,7 @@ SrsGoApiApi::~SrsGoApiApi() | @@ -70,7 +70,7 @@ SrsGoApiApi::~SrsGoApiApi() | ||
| 70 | { | 70 | { |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | -int SrsGoApiApi::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 73 | +int SrsGoApiApi::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 74 | { | 74 | { |
| 75 | std::stringstream ss; | 75 | std::stringstream ss; |
| 76 | 76 | ||
| @@ -92,7 +92,7 @@ SrsGoApiV1::~SrsGoApiV1() | @@ -92,7 +92,7 @@ SrsGoApiV1::~SrsGoApiV1() | ||
| 92 | { | 92 | { |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | -int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 95 | +int SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 96 | { | 96 | { |
| 97 | std::stringstream ss; | 97 | std::stringstream ss; |
| 98 | 98 | ||
| @@ -123,7 +123,7 @@ SrsGoApiVersion::~SrsGoApiVersion() | @@ -123,7 +123,7 @@ SrsGoApiVersion::~SrsGoApiVersion() | ||
| 123 | { | 123 | { |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | -int SrsGoApiVersion::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 126 | +int SrsGoApiVersion::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 127 | { | 127 | { |
| 128 | std::stringstream ss; | 128 | std::stringstream ss; |
| 129 | 129 | ||
| @@ -148,7 +148,7 @@ SrsGoApiSummaries::~SrsGoApiSummaries() | @@ -148,7 +148,7 @@ SrsGoApiSummaries::~SrsGoApiSummaries() | ||
| 148 | { | 148 | { |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | -int SrsGoApiSummaries::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 151 | +int SrsGoApiSummaries::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 152 | { | 152 | { |
| 153 | std::stringstream ss; | 153 | std::stringstream ss; |
| 154 | srs_api_dump_summaries(ss); | 154 | srs_api_dump_summaries(ss); |
| @@ -163,7 +163,7 @@ SrsGoApiRusages::~SrsGoApiRusages() | @@ -163,7 +163,7 @@ SrsGoApiRusages::~SrsGoApiRusages() | ||
| 163 | { | 163 | { |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | -int SrsGoApiRusages::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* req) | 166 | +int SrsGoApiRusages::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* req) |
| 167 | { | 167 | { |
| 168 | std::stringstream ss; | 168 | std::stringstream ss; |
| 169 | 169 | ||
| @@ -204,7 +204,7 @@ SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats() | @@ -204,7 +204,7 @@ SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats() | ||
| 204 | { | 204 | { |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | -int SrsGoApiSelfProcStats::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 207 | +int SrsGoApiSelfProcStats::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 208 | { | 208 | { |
| 209 | std::stringstream ss; | 209 | std::stringstream ss; |
| 210 | 210 | ||
| @@ -274,7 +274,7 @@ SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats() | @@ -274,7 +274,7 @@ SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats() | ||
| 274 | { | 274 | { |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | -int SrsGoApiSystemProcStats::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 277 | +int SrsGoApiSystemProcStats::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 278 | { | 278 | { |
| 279 | std::stringstream ss; | 279 | std::stringstream ss; |
| 280 | 280 | ||
| @@ -309,7 +309,7 @@ SrsGoApiMemInfos::~SrsGoApiMemInfos() | @@ -309,7 +309,7 @@ SrsGoApiMemInfos::~SrsGoApiMemInfos() | ||
| 309 | { | 309 | { |
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | -int SrsGoApiMemInfos::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 312 | +int SrsGoApiMemInfos::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 313 | { | 313 | { |
| 314 | std::stringstream ss; | 314 | std::stringstream ss; |
| 315 | 315 | ||
| @@ -345,7 +345,7 @@ SrsGoApiAuthors::~SrsGoApiAuthors() | @@ -345,7 +345,7 @@ SrsGoApiAuthors::~SrsGoApiAuthors() | ||
| 345 | { | 345 | { |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | -int SrsGoApiAuthors::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 348 | +int SrsGoApiAuthors::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 349 | { | 349 | { |
| 350 | std::stringstream ss; | 350 | std::stringstream ss; |
| 351 | 351 | ||
| @@ -370,9 +370,9 @@ SrsGoApiRequests::~SrsGoApiRequests() | @@ -370,9 +370,9 @@ SrsGoApiRequests::~SrsGoApiRequests() | ||
| 370 | { | 370 | { |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | -int SrsGoApiRequests::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 373 | +int SrsGoApiRequests::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 374 | { | 374 | { |
| 375 | - SrsHttpMessage* req = r; | 375 | + ISrsHttpMessage* req = r; |
| 376 | 376 | ||
| 377 | std::stringstream ss; | 377 | std::stringstream ss; |
| 378 | 378 | ||
| @@ -431,7 +431,7 @@ SrsGoApiVhosts::~SrsGoApiVhosts() | @@ -431,7 +431,7 @@ SrsGoApiVhosts::~SrsGoApiVhosts() | ||
| 431 | { | 431 | { |
| 432 | } | 432 | } |
| 433 | 433 | ||
| 434 | -int SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 434 | +int SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 435 | { | 435 | { |
| 436 | std::stringstream data; | 436 | std::stringstream data; |
| 437 | SrsStatistic* stat = SrsStatistic::instance(); | 437 | SrsStatistic* stat = SrsStatistic::instance(); |
| @@ -456,7 +456,7 @@ SrsGoApiStreams::~SrsGoApiStreams() | @@ -456,7 +456,7 @@ SrsGoApiStreams::~SrsGoApiStreams() | ||
| 456 | { | 456 | { |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | -int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 459 | +int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 460 | { | 460 | { |
| 461 | std::stringstream data; | 461 | std::stringstream data; |
| 462 | SrsStatistic* stat = SrsStatistic::instance(); | 462 | SrsStatistic* stat = SrsStatistic::instance(); |
| @@ -529,7 +529,7 @@ int SrsHttpApi::do_cycle() | @@ -529,7 +529,7 @@ int SrsHttpApi::do_cycle() | ||
| 529 | 529 | ||
| 530 | // process http messages. | 530 | // process http messages. |
| 531 | for (;;) { | 531 | for (;;) { |
| 532 | - SrsHttpMessage* req = NULL; | 532 | + ISrsHttpMessage* req = NULL; |
| 533 | 533 | ||
| 534 | // get a http message | 534 | // get a http message |
| 535 | if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) { | 535 | if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) { |
| @@ -540,7 +540,7 @@ int SrsHttpApi::do_cycle() | @@ -540,7 +540,7 @@ int SrsHttpApi::do_cycle() | ||
| 540 | srs_assert(req); | 540 | srs_assert(req); |
| 541 | 541 | ||
| 542 | // always free it in this scope. | 542 | // always free it in this scope. |
| 543 | - SrsAutoFree(SrsHttpMessage, req); | 543 | + SrsAutoFree(ISrsHttpMessage, req); |
| 544 | 544 | ||
| 545 | // TODO: FIXME: use the post body. | 545 | // TODO: FIXME: use the post body. |
| 546 | std::string res; | 546 | std::string res; |
| @@ -566,7 +566,7 @@ int SrsHttpApi::do_cycle() | @@ -566,7 +566,7 @@ int SrsHttpApi::do_cycle() | ||
| 566 | return ret; | 566 | return ret; |
| 567 | } | 567 | } |
| 568 | 568 | ||
| 569 | -int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 569 | +int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 570 | { | 570 | { |
| 571 | int ret = ERROR_SUCCESS; | 571 | int ret = ERROR_SUCCESS; |
| 572 | 572 |
| @@ -33,7 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -33,7 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 33 | #ifdef SRS_AUTO_HTTP_API | 33 | #ifdef SRS_AUTO_HTTP_API |
| 34 | 34 | ||
| 35 | class SrsStSocket; | 35 | class SrsStSocket; |
| 36 | -class SrsHttpMessage; | 36 | +class ISrsHttpMessage; |
| 37 | class SrsHttpParser; | 37 | class SrsHttpParser; |
| 38 | class SrsHttpHandler; | 38 | class SrsHttpHandler; |
| 39 | 39 | ||
| @@ -48,7 +48,7 @@ public: | @@ -48,7 +48,7 @@ public: | ||
| 48 | SrsGoApiRoot(); | 48 | SrsGoApiRoot(); |
| 49 | virtual ~SrsGoApiRoot(); | 49 | virtual ~SrsGoApiRoot(); |
| 50 | public: | 50 | public: |
| 51 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 51 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | class SrsGoApiApi : public ISrsHttpHandler | 54 | class SrsGoApiApi : public ISrsHttpHandler |
| @@ -57,7 +57,7 @@ public: | @@ -57,7 +57,7 @@ public: | ||
| 57 | SrsGoApiApi(); | 57 | SrsGoApiApi(); |
| 58 | virtual ~SrsGoApiApi(); | 58 | virtual ~SrsGoApiApi(); |
| 59 | public: | 59 | public: |
| 60 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 60 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | class SrsGoApiV1 : public ISrsHttpHandler | 63 | class SrsGoApiV1 : public ISrsHttpHandler |
| @@ -66,7 +66,7 @@ public: | @@ -66,7 +66,7 @@ public: | ||
| 66 | SrsGoApiV1(); | 66 | SrsGoApiV1(); |
| 67 | virtual ~SrsGoApiV1(); | 67 | virtual ~SrsGoApiV1(); |
| 68 | public: | 68 | public: |
| 69 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 69 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| 72 | class SrsGoApiVersion : public ISrsHttpHandler | 72 | class SrsGoApiVersion : public ISrsHttpHandler |
| @@ -75,7 +75,7 @@ public: | @@ -75,7 +75,7 @@ public: | ||
| 75 | SrsGoApiVersion(); | 75 | SrsGoApiVersion(); |
| 76 | virtual ~SrsGoApiVersion(); | 76 | virtual ~SrsGoApiVersion(); |
| 77 | public: | 77 | public: |
| 78 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 78 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | class SrsGoApiSummaries : public ISrsHttpHandler | 81 | class SrsGoApiSummaries : public ISrsHttpHandler |
| @@ -84,7 +84,7 @@ public: | @@ -84,7 +84,7 @@ public: | ||
| 84 | SrsGoApiSummaries(); | 84 | SrsGoApiSummaries(); |
| 85 | virtual ~SrsGoApiSummaries(); | 85 | virtual ~SrsGoApiSummaries(); |
| 86 | public: | 86 | public: |
| 87 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 87 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | class SrsGoApiRusages : public ISrsHttpHandler | 90 | class SrsGoApiRusages : public ISrsHttpHandler |
| @@ -93,7 +93,7 @@ public: | @@ -93,7 +93,7 @@ public: | ||
| 93 | SrsGoApiRusages(); | 93 | SrsGoApiRusages(); |
| 94 | virtual ~SrsGoApiRusages(); | 94 | virtual ~SrsGoApiRusages(); |
| 95 | public: | 95 | public: |
| 96 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 96 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | class SrsGoApiSelfProcStats : public ISrsHttpHandler | 99 | class SrsGoApiSelfProcStats : public ISrsHttpHandler |
| @@ -102,7 +102,7 @@ public: | @@ -102,7 +102,7 @@ public: | ||
| 102 | SrsGoApiSelfProcStats(); | 102 | SrsGoApiSelfProcStats(); |
| 103 | virtual ~SrsGoApiSelfProcStats(); | 103 | virtual ~SrsGoApiSelfProcStats(); |
| 104 | public: | 104 | public: |
| 105 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 105 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | class SrsGoApiSystemProcStats : public ISrsHttpHandler | 108 | class SrsGoApiSystemProcStats : public ISrsHttpHandler |
| @@ -111,7 +111,7 @@ public: | @@ -111,7 +111,7 @@ public: | ||
| 111 | SrsGoApiSystemProcStats(); | 111 | SrsGoApiSystemProcStats(); |
| 112 | virtual ~SrsGoApiSystemProcStats(); | 112 | virtual ~SrsGoApiSystemProcStats(); |
| 113 | public: | 113 | public: |
| 114 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 114 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 117 | class SrsGoApiMemInfos : public ISrsHttpHandler | 117 | class SrsGoApiMemInfos : public ISrsHttpHandler |
| @@ -120,7 +120,7 @@ public: | @@ -120,7 +120,7 @@ public: | ||
| 120 | SrsGoApiMemInfos(); | 120 | SrsGoApiMemInfos(); |
| 121 | virtual ~SrsGoApiMemInfos(); | 121 | virtual ~SrsGoApiMemInfos(); |
| 122 | public: | 122 | public: |
| 123 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 123 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | class SrsGoApiAuthors : public ISrsHttpHandler | 126 | class SrsGoApiAuthors : public ISrsHttpHandler |
| @@ -129,7 +129,7 @@ public: | @@ -129,7 +129,7 @@ public: | ||
| 129 | SrsGoApiAuthors(); | 129 | SrsGoApiAuthors(); |
| 130 | virtual ~SrsGoApiAuthors(); | 130 | virtual ~SrsGoApiAuthors(); |
| 131 | public: | 131 | public: |
| 132 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 132 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 133 | }; | 133 | }; |
| 134 | 134 | ||
| 135 | class SrsGoApiRequests : public ISrsHttpHandler | 135 | class SrsGoApiRequests : public ISrsHttpHandler |
| @@ -138,7 +138,7 @@ public: | @@ -138,7 +138,7 @@ public: | ||
| 138 | SrsGoApiRequests(); | 138 | SrsGoApiRequests(); |
| 139 | virtual ~SrsGoApiRequests(); | 139 | virtual ~SrsGoApiRequests(); |
| 140 | public: | 140 | public: |
| 141 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 141 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 142 | }; | 142 | }; |
| 143 | 143 | ||
| 144 | class SrsGoApiVhosts : public ISrsHttpHandler | 144 | class SrsGoApiVhosts : public ISrsHttpHandler |
| @@ -147,7 +147,7 @@ public: | @@ -147,7 +147,7 @@ public: | ||
| 147 | SrsGoApiVhosts(); | 147 | SrsGoApiVhosts(); |
| 148 | virtual ~SrsGoApiVhosts(); | 148 | virtual ~SrsGoApiVhosts(); |
| 149 | public: | 149 | public: |
| 150 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 150 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 151 | }; | 151 | }; |
| 152 | 152 | ||
| 153 | class SrsGoApiStreams : public ISrsHttpHandler | 153 | class SrsGoApiStreams : public ISrsHttpHandler |
| @@ -156,7 +156,7 @@ public: | @@ -156,7 +156,7 @@ public: | ||
| 156 | SrsGoApiStreams(); | 156 | SrsGoApiStreams(); |
| 157 | virtual ~SrsGoApiStreams(); | 157 | virtual ~SrsGoApiStreams(); |
| 158 | public: | 158 | public: |
| 159 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 159 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | class SrsHttpApi : public SrsConnection | 162 | class SrsHttpApi : public SrsConnection |
| @@ -177,7 +177,7 @@ public: | @@ -177,7 +177,7 @@ public: | ||
| 177 | protected: | 177 | protected: |
| 178 | virtual int do_cycle(); | 178 | virtual int do_cycle(); |
| 179 | private: | 179 | private: |
| 180 | - virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 180 | + virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 181 | }; | 181 | }; |
| 182 | 182 | ||
| 183 | #endif | 183 | #endif |
| @@ -71,7 +71,7 @@ int SrsHttpClient::initialize(string h, int p, int64_t t_us) | @@ -71,7 +71,7 @@ int SrsHttpClient::initialize(string h, int p, int64_t t_us) | ||
| 71 | return ret; | 71 | return ret; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | -int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) | 74 | +int SrsHttpClient::post(string path, string req, ISrsHttpMessage** ppmsg) |
| 75 | { | 75 | { |
| 76 | *ppmsg = NULL; | 76 | *ppmsg = NULL; |
| 77 | 77 | ||
| @@ -104,7 +104,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) | @@ -104,7 +104,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) | ||
| 104 | return ret; | 104 | return ret; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | - SrsHttpMessage* msg = NULL; | 107 | + ISrsHttpMessage* msg = NULL; |
| 108 | if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) { | 108 | if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) { |
| 109 | srs_error("parse http post response failed. ret=%d", ret); | 109 | srs_error("parse http post response failed. ret=%d", ret); |
| 110 | return ret; | 110 | return ret; |
| @@ -117,7 +117,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) | @@ -117,7 +117,7 @@ int SrsHttpClient::post(string path, string req, SrsHttpMessage** ppmsg) | ||
| 117 | return ret; | 117 | return ret; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | -int SrsHttpClient::get(string path, std::string req, SrsHttpMessage** ppmsg) | 120 | +int SrsHttpClient::get(string path, std::string req, ISrsHttpMessage** ppmsg) |
| 121 | { | 121 | { |
| 122 | *ppmsg = NULL; | 122 | *ppmsg = NULL; |
| 123 | 123 | ||
| @@ -150,7 +150,7 @@ int SrsHttpClient::get(string path, std::string req, SrsHttpMessage** ppmsg) | @@ -150,7 +150,7 @@ int SrsHttpClient::get(string path, std::string req, SrsHttpMessage** ppmsg) | ||
| 150 | return ret; | 150 | return ret; |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | - SrsHttpMessage* msg = NULL; | 153 | + ISrsHttpMessage* msg = NULL; |
| 154 | if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) { | 154 | if ((ret = parser->parse_message(skt, NULL, &msg)) != ERROR_SUCCESS) { |
| 155 | srs_error("parse http post response failed. ret=%d", ret); | 155 | srs_error("parse http post response failed. ret=%d", ret); |
| 156 | return ret; | 156 | return ret; |
| @@ -37,7 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -37,7 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 37 | 37 | ||
| 38 | class SrsHttpUri; | 38 | class SrsHttpUri; |
| 39 | class SrsHttpParser; | 39 | class SrsHttpParser; |
| 40 | -class SrsHttpMessage; | 40 | +class ISrsHttpMessage; |
| 41 | class SrsStSocket; | 41 | class SrsStSocket; |
| 42 | 42 | ||
| 43 | // the default timeout for http client. | 43 | // the default timeout for http client. |
| @@ -73,14 +73,14 @@ public: | @@ -73,14 +73,14 @@ public: | ||
| 73 | * @param req the data post to uri. empty string to ignore. | 73 | * @param req the data post to uri. empty string to ignore. |
| 74 | * @param ppmsg output the http message to read the response. | 74 | * @param ppmsg output the http message to read the response. |
| 75 | */ | 75 | */ |
| 76 | - virtual int post(std::string path, std::string req, SrsHttpMessage** ppmsg); | 76 | + virtual int post(std::string path, std::string req, ISrsHttpMessage** ppmsg); |
| 77 | /** | 77 | /** |
| 78 | * to get data from the uri. | 78 | * to get data from the uri. |
| 79 | * @param the path to request on. | 79 | * @param the path to request on. |
| 80 | * @param req the data post to uri. empty string to ignore. | 80 | * @param req the data post to uri. empty string to ignore. |
| 81 | * @param ppmsg output the http message to read the response. | 81 | * @param ppmsg output the http message to read the response. |
| 82 | */ | 82 | */ |
| 83 | - virtual int get(std::string path, std::string req, SrsHttpMessage** ppmsg); | 83 | + virtual int get(std::string path, std::string req, ISrsHttpMessage** ppmsg); |
| 84 | private: | 84 | private: |
| 85 | virtual void disconnect(); | 85 | virtual void disconnect(); |
| 86 | virtual int connect(); | 86 | virtual int connect(); |
| @@ -60,7 +60,7 @@ SrsVodStream::~SrsVodStream() | @@ -60,7 +60,7 @@ SrsVodStream::~SrsVodStream() | ||
| 60 | { | 60 | { |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | -int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) | 63 | +int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int offset) |
| 64 | { | 64 | { |
| 65 | int ret = ERROR_SUCCESS; | 65 | int ret = ERROR_SUCCESS; |
| 66 | 66 | ||
| @@ -144,7 +144,7 @@ int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, | @@ -144,7 +144,7 @@ int SrsVodStream::serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, | ||
| 144 | return ret; | 144 | return ret; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | -int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int start, int end) | 147 | +int SrsVodStream::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int start, int end) |
| 148 | { | 148 | { |
| 149 | int ret = ERROR_SUCCESS; | 149 | int ret = ERROR_SUCCESS; |
| 150 | 150 | ||
| @@ -567,7 +567,7 @@ SrsLiveStream::~SrsLiveStream() | @@ -567,7 +567,7 @@ SrsLiveStream::~SrsLiveStream() | ||
| 567 | srs_freep(req); | 567 | srs_freep(req); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | -int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 570 | +int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 571 | { | 571 | { |
| 572 | int ret = ERROR_SUCCESS; | 572 | int ret = ERROR_SUCCESS; |
| 573 | 573 | ||
| @@ -743,7 +743,7 @@ void SrsHlsM3u8Stream::set_m3u8(std::string v) | @@ -743,7 +743,7 @@ void SrsHlsM3u8Stream::set_m3u8(std::string v) | ||
| 743 | m3u8 = v; | 743 | m3u8 = v; |
| 744 | } | 744 | } |
| 745 | 745 | ||
| 746 | -int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 746 | +int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 747 | { | 747 | { |
| 748 | int ret = ERROR_SUCCESS; | 748 | int ret = ERROR_SUCCESS; |
| 749 | 749 | ||
| @@ -775,7 +775,7 @@ void SrsHlsTsStream::set_ts(std::string v) | @@ -775,7 +775,7 @@ void SrsHlsTsStream::set_ts(std::string v) | ||
| 775 | ts = v; | 775 | ts = v; |
| 776 | } | 776 | } |
| 777 | 777 | ||
| 778 | -int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 778 | +int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 779 | { | 779 | { |
| 780 | int ret = ERROR_SUCCESS; | 780 | int ret = ERROR_SUCCESS; |
| 781 | 781 | ||
| @@ -1110,7 +1110,7 @@ int SrsHttpServer::on_reload_vhost_hls(string vhost) | @@ -1110,7 +1110,7 @@ int SrsHttpServer::on_reload_vhost_hls(string vhost) | ||
| 1110 | return ret; | 1110 | return ret; |
| 1111 | } | 1111 | } |
| 1112 | 1112 | ||
| 1113 | -int SrsHttpServer::hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) | 1113 | +int SrsHttpServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) |
| 1114 | { | 1114 | { |
| 1115 | int ret = ERROR_SUCCESS; | 1115 | int ret = ERROR_SUCCESS; |
| 1116 | 1116 | ||
| @@ -1169,8 +1169,12 @@ int SrsHttpServer::hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) | @@ -1169,8 +1169,12 @@ int SrsHttpServer::hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) | ||
| 1169 | } | 1169 | } |
| 1170 | } | 1170 | } |
| 1171 | 1171 | ||
| 1172 | + // convert to concreate class. | ||
| 1173 | + SrsHttpMessage* hreq = dynamic_cast<SrsHttpMessage*>(request); | ||
| 1174 | + srs_assert(hreq); | ||
| 1175 | + | ||
| 1172 | // hijack for entry. | 1176 | // hijack for entry. |
| 1173 | - SrsRequest* r = request->to_request(vhost->arg0()); | 1177 | + SrsRequest* r = hreq->to_request(vhost->arg0()); |
| 1174 | SrsAutoFree(SrsRequest, r); | 1178 | SrsAutoFree(SrsRequest, r); |
| 1175 | SrsSource* s = SrsSource::fetch(r); | 1179 | SrsSource* s = SrsSource::fetch(r); |
| 1176 | if (!s) { | 1180 | if (!s) { |
| @@ -1389,7 +1393,7 @@ int SrsHttpConn::do_cycle() | @@ -1389,7 +1393,7 @@ int SrsHttpConn::do_cycle() | ||
| 1389 | 1393 | ||
| 1390 | // process http messages. | 1394 | // process http messages. |
| 1391 | for (;;) { | 1395 | for (;;) { |
| 1392 | - SrsHttpMessage* req = NULL; | 1396 | + ISrsHttpMessage* req = NULL; |
| 1393 | 1397 | ||
| 1394 | // get a http message | 1398 | // get a http message |
| 1395 | if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) { | 1399 | if ((ret = parser->parse_message(&skt, this, &req)) != ERROR_SUCCESS) { |
| @@ -1400,7 +1404,7 @@ int SrsHttpConn::do_cycle() | @@ -1400,7 +1404,7 @@ int SrsHttpConn::do_cycle() | ||
| 1400 | srs_assert(req); | 1404 | srs_assert(req); |
| 1401 | 1405 | ||
| 1402 | // always free it in this scope. | 1406 | // always free it in this scope. |
| 1403 | - SrsAutoFree(SrsHttpMessage, req); | 1407 | + SrsAutoFree(ISrsHttpMessage, req); |
| 1404 | 1408 | ||
| 1405 | // may should discard the body. | 1409 | // may should discard the body. |
| 1406 | if ((ret = on_got_http_message(req)) != ERROR_SUCCESS) { | 1410 | if ((ret = on_got_http_message(req)) != ERROR_SUCCESS) { |
| @@ -1423,7 +1427,7 @@ int SrsHttpConn::do_cycle() | @@ -1423,7 +1427,7 @@ int SrsHttpConn::do_cycle() | ||
| 1423 | return ret; | 1427 | return ret; |
| 1424 | } | 1428 | } |
| 1425 | 1429 | ||
| 1426 | -int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r) | 1430 | +int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) |
| 1427 | { | 1431 | { |
| 1428 | int ret = ERROR_SUCCESS; | 1432 | int ret = ERROR_SUCCESS; |
| 1429 | 1433 | ||
| @@ -1450,7 +1454,7 @@ SrsStaticHttpConn::~SrsStaticHttpConn() | @@ -1450,7 +1454,7 @@ SrsStaticHttpConn::~SrsStaticHttpConn() | ||
| 1450 | { | 1454 | { |
| 1451 | } | 1455 | } |
| 1452 | 1456 | ||
| 1453 | -int SrsStaticHttpConn::on_got_http_message(SrsHttpMessage* msg) | 1457 | +int SrsStaticHttpConn::on_got_http_message(ISrsHttpMessage* msg) |
| 1454 | { | 1458 | { |
| 1455 | int ret = ERROR_SUCCESS; | 1459 | int ret = ERROR_SUCCESS; |
| 1456 | 1460 |
| @@ -49,7 +49,7 @@ class SrsAacEncoder; | @@ -49,7 +49,7 @@ class SrsAacEncoder; | ||
| 49 | class SrsMp3Encoder; | 49 | class SrsMp3Encoder; |
| 50 | class SrsFlvEncoder; | 50 | class SrsFlvEncoder; |
| 51 | class SrsHttpParser; | 51 | class SrsHttpParser; |
| 52 | -class SrsHttpMessage; | 52 | +class ISrsHttpMessage; |
| 53 | class SrsHttpHandler; | 53 | class SrsHttpHandler; |
| 54 | class SrsMessageQueue; | 54 | class SrsMessageQueue; |
| 55 | class SrsSharedPtrMessage; | 55 | class SrsSharedPtrMessage; |
| @@ -66,8 +66,8 @@ public: | @@ -66,8 +66,8 @@ public: | ||
| 66 | SrsVodStream(std::string root_dir); | 66 | SrsVodStream(std::string root_dir); |
| 67 | virtual ~SrsVodStream(); | 67 | virtual ~SrsVodStream(); |
| 68 | protected: | 68 | protected: |
| 69 | - virtual int serve_flv_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int offset); | ||
| 70 | - virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, SrsHttpMessage* r, std::string fullpath, int start, int end); | 69 | + virtual int serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int offset); |
| 70 | + virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int start, int end); | ||
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | /** | 73 | /** |
| @@ -243,7 +243,7 @@ public: | @@ -243,7 +243,7 @@ public: | ||
| 243 | SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c); | 243 | SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c); |
| 244 | virtual ~SrsLiveStream(); | 244 | virtual ~SrsLiveStream(); |
| 245 | public: | 245 | public: |
| 246 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 246 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 247 | private: | 247 | private: |
| 248 | virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs); | 248 | virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs); |
| 249 | }; | 249 | }; |
| @@ -289,7 +289,7 @@ public: | @@ -289,7 +289,7 @@ public: | ||
| 289 | public: | 289 | public: |
| 290 | virtual void set_m3u8(std::string v); | 290 | virtual void set_m3u8(std::string v); |
| 291 | public: | 291 | public: |
| 292 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 292 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 293 | }; | 293 | }; |
| 294 | 294 | ||
| 295 | /** | 295 | /** |
| @@ -305,7 +305,7 @@ public: | @@ -305,7 +305,7 @@ public: | ||
| 305 | public: | 305 | public: |
| 306 | virtual void set_ts(std::string v); | 306 | virtual void set_ts(std::string v); |
| 307 | public: | 307 | public: |
| 308 | - virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 308 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 309 | }; | 309 | }; |
| 310 | 310 | ||
| 311 | /** | 311 | /** |
| @@ -365,7 +365,7 @@ public: | @@ -365,7 +365,7 @@ public: | ||
| 365 | virtual int on_reload_vhost_hls(std::string vhost); | 365 | virtual int on_reload_vhost_hls(std::string vhost); |
| 366 | // interface ISrsHttpMatchHijacker | 366 | // interface ISrsHttpMatchHijacker |
| 367 | public: | 367 | public: |
| 368 | - virtual int hijack(SrsHttpMessage* request, ISrsHttpHandler** ph); | 368 | + virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph); |
| 369 | private: | 369 | private: |
| 370 | virtual int initialize_static_file(); | 370 | virtual int initialize_static_file(); |
| 371 | virtual int initialize_flv_streaming(); | 371 | virtual int initialize_flv_streaming(); |
| @@ -392,9 +392,9 @@ protected: | @@ -392,9 +392,9 @@ protected: | ||
| 392 | // when got http message, | 392 | // when got http message, |
| 393 | // for the static service or api, discard any body. | 393 | // for the static service or api, discard any body. |
| 394 | // for the stream caster, for instance, http flv streaming, may discard the flv header or not. | 394 | // for the stream caster, for instance, http flv streaming, may discard the flv header or not. |
| 395 | - virtual int on_got_http_message(SrsHttpMessage* msg) = 0; | 395 | + virtual int on_got_http_message(ISrsHttpMessage* msg) = 0; |
| 396 | private: | 396 | private: |
| 397 | - virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r); | 397 | + virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); |
| 398 | }; | 398 | }; |
| 399 | 399 | ||
| 400 | class SrsStaticHttpConn : public SrsHttpConn | 400 | class SrsStaticHttpConn : public SrsHttpConn |
| @@ -403,7 +403,7 @@ public: | @@ -403,7 +403,7 @@ public: | ||
| 403 | SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m); | 403 | SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m); |
| 404 | virtual ~SrsStaticHttpConn(); | 404 | virtual ~SrsStaticHttpConn(); |
| 405 | public: | 405 | public: |
| 406 | - virtual int on_got_http_message(SrsHttpMessage* msg); | 406 | + virtual int on_got_http_message(ISrsHttpMessage* msg); |
| 407 | }; | 407 | }; |
| 408 | 408 | ||
| 409 | #endif | 409 | #endif |
| @@ -371,11 +371,11 @@ int SrsHttpHooks::on_hls_notify(std::string url, SrsRequest* req, std::string ts | @@ -371,11 +371,11 @@ int SrsHttpHooks::on_hls_notify(std::string url, SrsRequest* req, std::string ts | ||
| 371 | } | 371 | } |
| 372 | srs_warn("GET %s", path.c_str()); | 372 | srs_warn("GET %s", path.c_str()); |
| 373 | 373 | ||
| 374 | - SrsHttpMessage* msg = NULL; | 374 | + ISrsHttpMessage* msg = NULL; |
| 375 | if ((ret = http.get(path.c_str(), "", &msg)) != ERROR_SUCCESS) { | 375 | if ((ret = http.get(path.c_str(), "", &msg)) != ERROR_SUCCESS) { |
| 376 | return ret; | 376 | return ret; |
| 377 | } | 377 | } |
| 378 | - SrsAutoFree(SrsHttpMessage, msg); | 378 | + SrsAutoFree(ISrsHttpMessage, msg); |
| 379 | 379 | ||
| 380 | int nb_buf = srs_min(nb_notify, SRS_HTTP_READ_BUFFER); | 380 | int nb_buf = srs_min(nb_notify, SRS_HTTP_READ_BUFFER); |
| 381 | char* buf = new char[nb_buf]; | 381 | char* buf = new char[nb_buf]; |
| @@ -416,11 +416,11 @@ int SrsHttpHooks::do_post(std::string url, std::string req, int& code, string& r | @@ -416,11 +416,11 @@ int SrsHttpHooks::do_post(std::string url, std::string req, int& code, string& r | ||
| 416 | return ret; | 416 | return ret; |
| 417 | } | 417 | } |
| 418 | 418 | ||
| 419 | - SrsHttpMessage* msg = NULL; | 419 | + ISrsHttpMessage* msg = NULL; |
| 420 | if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { | 420 | if ((ret = http.post(uri.get_path(), req, &msg)) != ERROR_SUCCESS) { |
| 421 | return ret; | 421 | return ret; |
| 422 | } | 422 | } |
| 423 | - SrsAutoFree(SrsHttpMessage, msg); | 423 | + SrsAutoFree(ISrsHttpMessage, msg); |
| 424 | 424 | ||
| 425 | code = msg->status_code(); | 425 | code = msg->status_code(); |
| 426 | if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { | 426 | if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) { |
| @@ -383,14 +383,14 @@ int SrsIngestSrsInput::parseM3u8(SrsHttpUri* url, double& td, double& duration) | @@ -383,14 +383,14 @@ int SrsIngestSrsInput::parseM3u8(SrsHttpUri* url, double& td, double& duration) | ||
| 383 | return ret; | 383 | return ret; |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | - SrsHttpMessage* msg = NULL; | 386 | + ISrsHttpMessage* msg = NULL; |
| 387 | if ((ret = client.get(url->get_path(), "", &msg)) != ERROR_SUCCESS) { | 387 | if ((ret = client.get(url->get_path(), "", &msg)) != ERROR_SUCCESS) { |
| 388 | srs_error("HTTP GET %s failed. ret=%d", url->get_url(), ret); | 388 | srs_error("HTTP GET %s failed. ret=%d", url->get_url(), ret); |
| 389 | return ret; | 389 | return ret; |
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | srs_assert(msg); | 392 | srs_assert(msg); |
| 393 | - SrsAutoFree(SrsHttpMessage, msg); | 393 | + SrsAutoFree(ISrsHttpMessage, msg); |
| 394 | 394 | ||
| 395 | std::string body; | 395 | std::string body; |
| 396 | if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) { | 396 | if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) { |
| @@ -605,14 +605,14 @@ int SrsIngestSrsInput::SrsTsPiece::fetch(string m3u8) | @@ -605,14 +605,14 @@ int SrsIngestSrsInput::SrsTsPiece::fetch(string m3u8) | ||
| 605 | return ret; | 605 | return ret; |
| 606 | } | 606 | } |
| 607 | 607 | ||
| 608 | - SrsHttpMessage* msg = NULL; | 608 | + ISrsHttpMessage* msg = NULL; |
| 609 | if ((ret = client.get(uri.get_path(), "", &msg)) != ERROR_SUCCESS) { | 609 | if ((ret = client.get(uri.get_path(), "", &msg)) != ERROR_SUCCESS) { |
| 610 | srs_error("HTTP GET %s failed. ret=%d", uri.get_url(), ret); | 610 | srs_error("HTTP GET %s failed. ret=%d", uri.get_url(), ret); |
| 611 | return ret; | 611 | return ret; |
| 612 | } | 612 | } |
| 613 | 613 | ||
| 614 | srs_assert(msg); | 614 | srs_assert(msg); |
| 615 | - SrsAutoFree(SrsHttpMessage, msg); | 615 | + SrsAutoFree(ISrsHttpMessage, msg); |
| 616 | 616 | ||
| 617 | if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) { | 617 | if ((ret = msg->body_read_all(body)) != ERROR_SUCCESS) { |
| 618 | srs_error("read ts failed. ret=%d", ret); | 618 | srs_error("read ts failed. ret=%d", ret); |
| @@ -22,3 +22,717 @@ | @@ -22,3 +22,717 @@ | ||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include <srs_http_stack.hpp> | 24 | #include <srs_http_stack.hpp> |
| 25 | + | ||
| 26 | +#include <sstream> | ||
| 27 | +using namespace std; | ||
| 28 | + | ||
| 29 | +#include <srs_kernel_error.hpp> | ||
| 30 | +#include <srs_kernel_log.hpp> | ||
| 31 | +#include <srs_kernel_utility.hpp> | ||
| 32 | +#include <srs_kernel_file.hpp> | ||
| 33 | + | ||
| 34 | +#define SRS_HTTP_DEFAULT_PAGE "index.html" | ||
| 35 | + | ||
| 36 | +// get the status text of code. | ||
| 37 | +string srs_generate_http_status_text(int status) | ||
| 38 | +{ | ||
| 39 | + static std::map<int, std::string> _status_map; | ||
| 40 | + if (_status_map.empty()) { | ||
| 41 | + _status_map[SRS_CONSTS_HTTP_Continue ] = SRS_CONSTS_HTTP_Continue_str ; | ||
| 42 | + _status_map[SRS_CONSTS_HTTP_SwitchingProtocols ] = SRS_CONSTS_HTTP_SwitchingProtocols_str ; | ||
| 43 | + _status_map[SRS_CONSTS_HTTP_OK ] = SRS_CONSTS_HTTP_OK_str ; | ||
| 44 | + _status_map[SRS_CONSTS_HTTP_Created ] = SRS_CONSTS_HTTP_Created_str ; | ||
| 45 | + _status_map[SRS_CONSTS_HTTP_Accepted ] = SRS_CONSTS_HTTP_Accepted_str ; | ||
| 46 | + _status_map[SRS_CONSTS_HTTP_NonAuthoritativeInformation ] = SRS_CONSTS_HTTP_NonAuthoritativeInformation_str ; | ||
| 47 | + _status_map[SRS_CONSTS_HTTP_NoContent ] = SRS_CONSTS_HTTP_NoContent_str ; | ||
| 48 | + _status_map[SRS_CONSTS_HTTP_ResetContent ] = SRS_CONSTS_HTTP_ResetContent_str ; | ||
| 49 | + _status_map[SRS_CONSTS_HTTP_PartialContent ] = SRS_CONSTS_HTTP_PartialContent_str ; | ||
| 50 | + _status_map[SRS_CONSTS_HTTP_MultipleChoices ] = SRS_CONSTS_HTTP_MultipleChoices_str ; | ||
| 51 | + _status_map[SRS_CONSTS_HTTP_MovedPermanently ] = SRS_CONSTS_HTTP_MovedPermanently_str ; | ||
| 52 | + _status_map[SRS_CONSTS_HTTP_Found ] = SRS_CONSTS_HTTP_Found_str ; | ||
| 53 | + _status_map[SRS_CONSTS_HTTP_SeeOther ] = SRS_CONSTS_HTTP_SeeOther_str ; | ||
| 54 | + _status_map[SRS_CONSTS_HTTP_NotModified ] = SRS_CONSTS_HTTP_NotModified_str ; | ||
| 55 | + _status_map[SRS_CONSTS_HTTP_UseProxy ] = SRS_CONSTS_HTTP_UseProxy_str ; | ||
| 56 | + _status_map[SRS_CONSTS_HTTP_TemporaryRedirect ] = SRS_CONSTS_HTTP_TemporaryRedirect_str ; | ||
| 57 | + _status_map[SRS_CONSTS_HTTP_BadRequest ] = SRS_CONSTS_HTTP_BadRequest_str ; | ||
| 58 | + _status_map[SRS_CONSTS_HTTP_Unauthorized ] = SRS_CONSTS_HTTP_Unauthorized_str ; | ||
| 59 | + _status_map[SRS_CONSTS_HTTP_PaymentRequired ] = SRS_CONSTS_HTTP_PaymentRequired_str ; | ||
| 60 | + _status_map[SRS_CONSTS_HTTP_Forbidden ] = SRS_CONSTS_HTTP_Forbidden_str ; | ||
| 61 | + _status_map[SRS_CONSTS_HTTP_NotFound ] = SRS_CONSTS_HTTP_NotFound_str ; | ||
| 62 | + _status_map[SRS_CONSTS_HTTP_MethodNotAllowed ] = SRS_CONSTS_HTTP_MethodNotAllowed_str ; | ||
| 63 | + _status_map[SRS_CONSTS_HTTP_NotAcceptable ] = SRS_CONSTS_HTTP_NotAcceptable_str ; | ||
| 64 | + _status_map[SRS_CONSTS_HTTP_ProxyAuthenticationRequired ] = SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str ; | ||
| 65 | + _status_map[SRS_CONSTS_HTTP_RequestTimeout ] = SRS_CONSTS_HTTP_RequestTimeout_str ; | ||
| 66 | + _status_map[SRS_CONSTS_HTTP_Conflict ] = SRS_CONSTS_HTTP_Conflict_str ; | ||
| 67 | + _status_map[SRS_CONSTS_HTTP_Gone ] = SRS_CONSTS_HTTP_Gone_str ; | ||
| 68 | + _status_map[SRS_CONSTS_HTTP_LengthRequired ] = SRS_CONSTS_HTTP_LengthRequired_str ; | ||
| 69 | + _status_map[SRS_CONSTS_HTTP_PreconditionFailed ] = SRS_CONSTS_HTTP_PreconditionFailed_str ; | ||
| 70 | + _status_map[SRS_CONSTS_HTTP_RequestEntityTooLarge ] = SRS_CONSTS_HTTP_RequestEntityTooLarge_str ; | ||
| 71 | + _status_map[SRS_CONSTS_HTTP_RequestURITooLarge ] = SRS_CONSTS_HTTP_RequestURITooLarge_str ; | ||
| 72 | + _status_map[SRS_CONSTS_HTTP_UnsupportedMediaType ] = SRS_CONSTS_HTTP_UnsupportedMediaType_str ; | ||
| 73 | + _status_map[SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable ] = SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str ; | ||
| 74 | + _status_map[SRS_CONSTS_HTTP_ExpectationFailed ] = SRS_CONSTS_HTTP_ExpectationFailed_str ; | ||
| 75 | + _status_map[SRS_CONSTS_HTTP_InternalServerError ] = SRS_CONSTS_HTTP_InternalServerError_str ; | ||
| 76 | + _status_map[SRS_CONSTS_HTTP_NotImplemented ] = SRS_CONSTS_HTTP_NotImplemented_str ; | ||
| 77 | + _status_map[SRS_CONSTS_HTTP_BadGateway ] = SRS_CONSTS_HTTP_BadGateway_str ; | ||
| 78 | + _status_map[SRS_CONSTS_HTTP_ServiceUnavailable ] = SRS_CONSTS_HTTP_ServiceUnavailable_str ; | ||
| 79 | + _status_map[SRS_CONSTS_HTTP_GatewayTimeout ] = SRS_CONSTS_HTTP_GatewayTimeout_str ; | ||
| 80 | + _status_map[SRS_CONSTS_HTTP_HTTPVersionNotSupported ] = SRS_CONSTS_HTTP_HTTPVersionNotSupported_str ; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + std::string status_text; | ||
| 84 | + if (_status_map.find(status) == _status_map.end()) { | ||
| 85 | + status_text = "Status Unknown"; | ||
| 86 | + } else { | ||
| 87 | + status_text = _status_map[status]; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + return status_text; | ||
| 91 | +} | ||
| 92 | + | ||
| 93 | +// bodyAllowedForStatus reports whether a given response status code | ||
| 94 | +// permits a body. See RFC2616, section 4.4. | ||
| 95 | +bool srs_go_http_body_allowd(int status) | ||
| 96 | +{ | ||
| 97 | + if (status >= 100 && status <= 199) { | ||
| 98 | + return false; | ||
| 99 | + } else if (status == 204 || status == 304) { | ||
| 100 | + return false; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + return true; | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +// DetectContentType implements the algorithm described | ||
| 107 | +// at http://mimesniff.spec.whatwg.org/ to determine the | ||
| 108 | +// Content-Type of the given data. It considers at most the | ||
| 109 | +// first 512 bytes of data. DetectContentType always returns | ||
| 110 | +// a valid MIME type: if it cannot determine a more specific one, it | ||
| 111 | +// returns "application/octet-stream". | ||
| 112 | +string srs_go_http_detect(char* data, int size) | ||
| 113 | +{ | ||
| 114 | + // detect only when data specified. | ||
| 115 | + if (data) { | ||
| 116 | + } | ||
| 117 | + return "application/octet-stream"; // fallback | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +// Error replies to the request with the specified error message and HTTP code. | ||
| 121 | +// The error message should be plain text. | ||
| 122 | +int srs_go_http_error(ISrsHttpResponseWriter* w, int code, string error) | ||
| 123 | +{ | ||
| 124 | + int ret = ERROR_SUCCESS; | ||
| 125 | + | ||
| 126 | + w->header()->set_content_type("text/plain; charset=utf-8"); | ||
| 127 | + w->header()->set_content_length(error.length()); | ||
| 128 | + w->write_header(code); | ||
| 129 | + w->write((char*)error.data(), (int)error.length()); | ||
| 130 | + | ||
| 131 | + return ret; | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +int srs_http_response_json(ISrsHttpResponseWriter* w, string data) | ||
| 135 | +{ | ||
| 136 | + SrsHttpHeader* h = w->header(); | ||
| 137 | + | ||
| 138 | + h->set_content_length(data.length()); | ||
| 139 | + h->set_content_type("application/json"); | ||
| 140 | + | ||
| 141 | + return w->write((char*)data.data(), (int)data.length()); | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +SrsHttpHeader::SrsHttpHeader() | ||
| 145 | +{ | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +SrsHttpHeader::~SrsHttpHeader() | ||
| 149 | +{ | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +void SrsHttpHeader::set(string key, string value) | ||
| 153 | +{ | ||
| 154 | + headers[key] = value; | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +string SrsHttpHeader::get(string key) | ||
| 158 | +{ | ||
| 159 | + std::string v; | ||
| 160 | + | ||
| 161 | + if (headers.find(key) != headers.end()) { | ||
| 162 | + v = headers[key]; | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + return v; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +int64_t SrsHttpHeader::content_length() | ||
| 169 | +{ | ||
| 170 | + std::string cl = get("Content-Length"); | ||
| 171 | + | ||
| 172 | + if (cl.empty()) { | ||
| 173 | + return -1; | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + return (int64_t)::atof(cl.c_str()); | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +void SrsHttpHeader::set_content_length(int64_t size) | ||
| 180 | +{ | ||
| 181 | + char buf[64]; | ||
| 182 | + snprintf(buf, sizeof(buf), "%"PRId64, size); | ||
| 183 | + set("Content-Length", buf); | ||
| 184 | +} | ||
| 185 | + | ||
| 186 | +string SrsHttpHeader::content_type() | ||
| 187 | +{ | ||
| 188 | + return get("Content-Type"); | ||
| 189 | +} | ||
| 190 | + | ||
| 191 | +void SrsHttpHeader::set_content_type(string ct) | ||
| 192 | +{ | ||
| 193 | + set("Content-Type", ct); | ||
| 194 | +} | ||
| 195 | + | ||
| 196 | +void SrsHttpHeader::write(stringstream& ss) | ||
| 197 | +{ | ||
| 198 | + std::map<std::string, std::string>::iterator it; | ||
| 199 | + for (it = headers.begin(); it != headers.end(); ++it) { | ||
| 200 | + ss << it->first << ": " << it->second << SRS_HTTP_CRLF; | ||
| 201 | + } | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +ISrsHttpResponseWriter::ISrsHttpResponseWriter() | ||
| 205 | +{ | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +ISrsHttpResponseWriter::~ISrsHttpResponseWriter() | ||
| 209 | +{ | ||
| 210 | +} | ||
| 211 | + | ||
| 212 | +ISrsHttpResponseReader::ISrsHttpResponseReader() | ||
| 213 | +{ | ||
| 214 | +} | ||
| 215 | + | ||
| 216 | +ISrsHttpResponseReader::~ISrsHttpResponseReader() | ||
| 217 | +{ | ||
| 218 | +} | ||
| 219 | + | ||
| 220 | +ISrsHttpHandler::ISrsHttpHandler() | ||
| 221 | +{ | ||
| 222 | + entry = NULL; | ||
| 223 | +} | ||
| 224 | + | ||
| 225 | +ISrsHttpHandler::~ISrsHttpHandler() | ||
| 226 | +{ | ||
| 227 | +} | ||
| 228 | + | ||
| 229 | +SrsHttpRedirectHandler::SrsHttpRedirectHandler(string u, int c) | ||
| 230 | +{ | ||
| 231 | + url = u; | ||
| 232 | + code = c; | ||
| 233 | +} | ||
| 234 | + | ||
| 235 | +SrsHttpRedirectHandler::~SrsHttpRedirectHandler() | ||
| 236 | +{ | ||
| 237 | +} | ||
| 238 | + | ||
| 239 | +int SrsHttpRedirectHandler::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) | ||
| 240 | +{ | ||
| 241 | + int ret = ERROR_SUCCESS; | ||
| 242 | + // TODO: FIXME: implements it. | ||
| 243 | + return ret; | ||
| 244 | +} | ||
| 245 | + | ||
| 246 | +SrsHttpNotFoundHandler::SrsHttpNotFoundHandler() | ||
| 247 | +{ | ||
| 248 | +} | ||
| 249 | + | ||
| 250 | +SrsHttpNotFoundHandler::~SrsHttpNotFoundHandler() | ||
| 251 | +{ | ||
| 252 | +} | ||
| 253 | + | ||
| 254 | +int SrsHttpNotFoundHandler::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) | ||
| 255 | +{ | ||
| 256 | + return srs_go_http_error(w, SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str); | ||
| 257 | +} | ||
| 258 | + | ||
| 259 | +SrsHttpFileServer::SrsHttpFileServer(string root_dir) | ||
| 260 | +{ | ||
| 261 | + dir = root_dir; | ||
| 262 | +} | ||
| 263 | + | ||
| 264 | +SrsHttpFileServer::~SrsHttpFileServer() | ||
| 265 | +{ | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +int SrsHttpFileServer::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) | ||
| 269 | +{ | ||
| 270 | + string upath = r->path(); | ||
| 271 | + | ||
| 272 | + // add default pages. | ||
| 273 | + if (srs_string_ends_with(upath, "/")) { | ||
| 274 | + upath += SRS_HTTP_DEFAULT_PAGE; | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + string fullpath = dir + "/"; | ||
| 278 | + | ||
| 279 | + // remove the virtual directory. | ||
| 280 | + srs_assert(entry); | ||
| 281 | + size_t pos = entry->pattern.find("/"); | ||
| 282 | + if (upath.length() > entry->pattern.length() && pos != string::npos) { | ||
| 283 | + fullpath += upath.substr(entry->pattern.length() - pos); | ||
| 284 | + } else { | ||
| 285 | + fullpath += upath; | ||
| 286 | + } | ||
| 287 | + | ||
| 288 | + // stat current dir, if exists, return error. | ||
| 289 | + if (!srs_path_exists(fullpath)) { | ||
| 290 | + srs_warn("http miss file=%s, pattern=%s, upath=%s", | ||
| 291 | + fullpath.c_str(), entry->pattern.c_str(), upath.c_str()); | ||
| 292 | + return SrsHttpNotFoundHandler().serve_http(w, r); | ||
| 293 | + } | ||
| 294 | + srs_trace("http match file=%s, pattern=%s, upath=%s", | ||
| 295 | + fullpath.c_str(), entry->pattern.c_str(), upath.c_str()); | ||
| 296 | + | ||
| 297 | + // handle file according to its extension. | ||
| 298 | + // use vod stream for .flv/.fhv | ||
| 299 | + if (srs_string_ends_with(fullpath, ".flv") || srs_string_ends_with(fullpath, ".fhv")) { | ||
| 300 | + return serve_flv_file(w, r, fullpath); | ||
| 301 | + } else if (srs_string_ends_with(fullpath, ".mp4")) { | ||
| 302 | + return serve_mp4_file(w, r, fullpath); | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + // serve common static file. | ||
| 306 | + return serve_file(w, r, fullpath); | ||
| 307 | +} | ||
| 308 | + | ||
| 309 | +int SrsHttpFileServer::serve_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath) | ||
| 310 | +{ | ||
| 311 | + int ret = ERROR_SUCCESS; | ||
| 312 | + | ||
| 313 | + // open the target file. | ||
| 314 | + SrsFileReader fs; | ||
| 315 | + | ||
| 316 | + if ((ret = fs.open(fullpath)) != ERROR_SUCCESS) { | ||
| 317 | + srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret); | ||
| 318 | + return ret; | ||
| 319 | + } | ||
| 320 | + | ||
| 321 | + int64_t length = fs.filesize(); | ||
| 322 | + | ||
| 323 | + // unset the content length to encode in chunked encoding. | ||
| 324 | + w->header()->set_content_length(length); | ||
| 325 | + | ||
| 326 | + static std::map<std::string, std::string> _mime; | ||
| 327 | + if (_mime.empty()) { | ||
| 328 | + _mime[".ts"] = "video/MP2T"; | ||
| 329 | + _mime[".flv"] = "video/x-flv"; | ||
| 330 | + _mime[".m4v"] = "video/x-m4v"; | ||
| 331 | + _mime[".3gpp"] = "video/3gpp"; | ||
| 332 | + _mime[".3gp"] = "video/3gpp"; | ||
| 333 | + _mime[".mp4"] = "video/mp4"; | ||
| 334 | + _mime[".aac"] = "audio/x-aac"; | ||
| 335 | + _mime[".mp3"] = "audio/mpeg"; | ||
| 336 | + _mime[".m4a"] = "audio/x-m4a"; | ||
| 337 | + _mime[".ogg"] = "audio/ogg"; | ||
| 338 | + // @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 5. | ||
| 339 | + _mime[".m3u8"] = "application/vnd.apple.mpegurl"; // application/x-mpegURL | ||
| 340 | + _mime[".rss"] = "application/rss+xml"; | ||
| 341 | + _mime[".json"] = "application/json"; | ||
| 342 | + _mime[".swf"] = "application/x-shockwave-flash"; | ||
| 343 | + _mime[".doc"] = "application/msword"; | ||
| 344 | + _mime[".zip"] = "application/zip"; | ||
| 345 | + _mime[".rar"] = "application/x-rar-compressed"; | ||
| 346 | + _mime[".xml"] = "text/xml"; | ||
| 347 | + _mime[".html"] = "text/html"; | ||
| 348 | + _mime[".js"] = "text/javascript"; | ||
| 349 | + _mime[".css"] = "text/css"; | ||
| 350 | + _mime[".ico"] = "image/x-icon"; | ||
| 351 | + _mime[".png"] = "image/png"; | ||
| 352 | + _mime[".jpeg"] = "image/jpeg"; | ||
| 353 | + _mime[".jpg"] = "image/jpeg"; | ||
| 354 | + _mime[".gif"] = "image/gif"; | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + if (true) { | ||
| 358 | + size_t pos; | ||
| 359 | + std::string ext = fullpath; | ||
| 360 | + if ((pos = ext.rfind(".")) != string::npos) { | ||
| 361 | + ext = ext.substr(pos); | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + if (_mime.find(ext) == _mime.end()) { | ||
| 365 | + w->header()->set_content_type("application/octet-stream"); | ||
| 366 | + } else { | ||
| 367 | + w->header()->set_content_type(_mime[ext]); | ||
| 368 | + } | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + // write body. | ||
| 372 | + int64_t left = length; | ||
| 373 | + if ((ret = copy(w, &fs, r, (int)left)) != ERROR_SUCCESS) { | ||
| 374 | + if (!srs_is_client_gracefully_close(ret)) { | ||
| 375 | + srs_error("read file=%s size=%d failed, ret=%d", fullpath.c_str(), left, ret); | ||
| 376 | + } | ||
| 377 | + return ret; | ||
| 378 | + } | ||
| 379 | + | ||
| 380 | + return w->final_request(); | ||
| 381 | +} | ||
| 382 | + | ||
| 383 | +int SrsHttpFileServer::serve_flv_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath) | ||
| 384 | +{ | ||
| 385 | + std::string start = r->query_get("start"); | ||
| 386 | + if (start.empty()) { | ||
| 387 | + return serve_file(w, r, fullpath); | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + int offset = ::atoi(start.c_str()); | ||
| 391 | + if (offset <= 0) { | ||
| 392 | + return serve_file(w, r, fullpath); | ||
| 393 | + } | ||
| 394 | + | ||
| 395 | + return serve_flv_stream(w, r, fullpath, offset); | ||
| 396 | +} | ||
| 397 | + | ||
| 398 | +int SrsHttpFileServer::serve_mp4_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath) | ||
| 399 | +{ | ||
| 400 | + // for flash to request mp4 range in query string. | ||
| 401 | + // for example, http://digitalprimates.net/dash/DashTest.html?url=http://dashdemo.edgesuite.net/digitalprimates/nexus/oops-20120802-manifest.mpd | ||
| 402 | + std::string range = r->query_get("range"); | ||
| 403 | + // or, use bytes to request range, | ||
| 404 | + // for example, http://dashas.castlabs.com/demo/try.html | ||
| 405 | + if (range.empty()) { | ||
| 406 | + range = r->query_get("bytes"); | ||
| 407 | + } | ||
| 408 | + | ||
| 409 | + // rollback to serve whole file. | ||
| 410 | + size_t pos = string::npos; | ||
| 411 | + if (range.empty() || (pos = range.find("-")) == string::npos) { | ||
| 412 | + return serve_file(w, r, fullpath); | ||
| 413 | + } | ||
| 414 | + | ||
| 415 | + // parse the start in query string | ||
| 416 | + int start = 0; | ||
| 417 | + if (pos > 0) { | ||
| 418 | + start = ::atoi(range.substr(0, pos).c_str()); | ||
| 419 | + } | ||
| 420 | + | ||
| 421 | + // parse end in query string. | ||
| 422 | + int end = -1; | ||
| 423 | + if (pos < range.length() - 1) { | ||
| 424 | + end = ::atoi(range.substr(pos + 1).c_str()); | ||
| 425 | + } | ||
| 426 | + | ||
| 427 | + // invalid param, serve as whole mp4 file. | ||
| 428 | + if (start < 0 || (end != -1 && start > end)) { | ||
| 429 | + return serve_file(w, r, fullpath); | ||
| 430 | + } | ||
| 431 | + | ||
| 432 | + return serve_mp4_stream(w, r, fullpath, start, end); | ||
| 433 | +} | ||
| 434 | + | ||
| 435 | +int SrsHttpFileServer::serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int offset) | ||
| 436 | +{ | ||
| 437 | + return serve_file(w, r, fullpath); | ||
| 438 | +} | ||
| 439 | + | ||
| 440 | +int SrsHttpFileServer::serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, string fullpath, int start, int end) | ||
| 441 | +{ | ||
| 442 | + return serve_file(w, r, fullpath); | ||
| 443 | +} | ||
| 444 | + | ||
| 445 | +int SrsHttpFileServer::copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, ISrsHttpMessage* r, int size) | ||
| 446 | +{ | ||
| 447 | + int ret = ERROR_SUCCESS; | ||
| 448 | + | ||
| 449 | + int left = size; | ||
| 450 | + char* buf = r->http_ts_send_buffer(); | ||
| 451 | + | ||
| 452 | + while (left > 0) { | ||
| 453 | + ssize_t nread = -1; | ||
| 454 | + int max_read = srs_min(left, SRS_HTTP_TS_SEND_BUFFER_SIZE); | ||
| 455 | + if ((ret = fs->read(buf, max_read, &nread)) != ERROR_SUCCESS) { | ||
| 456 | + break; | ||
| 457 | + } | ||
| 458 | + | ||
| 459 | + left -= nread; | ||
| 460 | + if ((ret = w->write(buf, (int)nread)) != ERROR_SUCCESS) { | ||
| 461 | + break; | ||
| 462 | + } | ||
| 463 | + } | ||
| 464 | + | ||
| 465 | + return ret; | ||
| 466 | +} | ||
| 467 | + | ||
| 468 | +SrsHttpMuxEntry::SrsHttpMuxEntry() | ||
| 469 | +{ | ||
| 470 | + enabled = true; | ||
| 471 | + explicit_match = false; | ||
| 472 | + handler = NULL; | ||
| 473 | +} | ||
| 474 | + | ||
| 475 | +SrsHttpMuxEntry::~SrsHttpMuxEntry() | ||
| 476 | +{ | ||
| 477 | + srs_freep(handler); | ||
| 478 | +} | ||
| 479 | + | ||
| 480 | +ISrsHttpMatchHijacker::ISrsHttpMatchHijacker() | ||
| 481 | +{ | ||
| 482 | +} | ||
| 483 | + | ||
| 484 | +ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker() | ||
| 485 | +{ | ||
| 486 | +} | ||
| 487 | + | ||
| 488 | +SrsHttpServeMux::SrsHttpServeMux() | ||
| 489 | +{ | ||
| 490 | +} | ||
| 491 | + | ||
| 492 | +SrsHttpServeMux::~SrsHttpServeMux() | ||
| 493 | +{ | ||
| 494 | + std::map<std::string, SrsHttpMuxEntry*>::iterator it; | ||
| 495 | + for (it = entries.begin(); it != entries.end(); ++it) { | ||
| 496 | + SrsHttpMuxEntry* entry = it->second; | ||
| 497 | + srs_freep(entry); | ||
| 498 | + } | ||
| 499 | + entries.clear(); | ||
| 500 | + | ||
| 501 | + vhosts.clear(); | ||
| 502 | + hijackers.clear(); | ||
| 503 | +} | ||
| 504 | + | ||
| 505 | +int SrsHttpServeMux::initialize() | ||
| 506 | +{ | ||
| 507 | + int ret = ERROR_SUCCESS; | ||
| 508 | + // TODO: FIXME: implements it. | ||
| 509 | + return ret; | ||
| 510 | +} | ||
| 511 | + | ||
| 512 | +void SrsHttpServeMux::hijack(ISrsHttpMatchHijacker* h) | ||
| 513 | +{ | ||
| 514 | + std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h); | ||
| 515 | + if (it != hijackers.end()) { | ||
| 516 | + return; | ||
| 517 | + } | ||
| 518 | + hijackers.push_back(h); | ||
| 519 | +} | ||
| 520 | + | ||
| 521 | +void SrsHttpServeMux::unhijack(ISrsHttpMatchHijacker* h) | ||
| 522 | +{ | ||
| 523 | + std::vector<ISrsHttpMatchHijacker*>::iterator it = ::find(hijackers.begin(), hijackers.end(), h); | ||
| 524 | + if (it == hijackers.end()) { | ||
| 525 | + return; | ||
| 526 | + } | ||
| 527 | + hijackers.erase(it); | ||
| 528 | +} | ||
| 529 | + | ||
| 530 | +int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler) | ||
| 531 | +{ | ||
| 532 | + int ret = ERROR_SUCCESS; | ||
| 533 | + | ||
| 534 | + srs_assert(handler); | ||
| 535 | + | ||
| 536 | + if (pattern.empty()) { | ||
| 537 | + ret = ERROR_HTTP_PATTERN_EMPTY; | ||
| 538 | + srs_error("http: empty pattern. ret=%d", ret); | ||
| 539 | + return ret; | ||
| 540 | + } | ||
| 541 | + | ||
| 542 | + if (entries.find(pattern) != entries.end()) { | ||
| 543 | + SrsHttpMuxEntry* exists = entries[pattern]; | ||
| 544 | + if (exists->explicit_match) { | ||
| 545 | + ret = ERROR_HTTP_PATTERN_DUPLICATED; | ||
| 546 | + srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret); | ||
| 547 | + return ret; | ||
| 548 | + } | ||
| 549 | + } | ||
| 550 | + | ||
| 551 | + std::string vhost = pattern; | ||
| 552 | + if (pattern.at(0) != '/') { | ||
| 553 | + if (pattern.find("/") != string::npos) { | ||
| 554 | + vhost = pattern.substr(0, pattern.find("/")); | ||
| 555 | + } | ||
| 556 | + vhosts[vhost] = handler; | ||
| 557 | + } | ||
| 558 | + | ||
| 559 | + if (true) { | ||
| 560 | + SrsHttpMuxEntry* entry = new SrsHttpMuxEntry(); | ||
| 561 | + entry->explicit_match = true; | ||
| 562 | + entry->handler = handler; | ||
| 563 | + entry->pattern = pattern; | ||
| 564 | + entry->handler->entry = entry; | ||
| 565 | + | ||
| 566 | + if (entries.find(pattern) != entries.end()) { | ||
| 567 | + SrsHttpMuxEntry* exists = entries[pattern]; | ||
| 568 | + srs_freep(exists); | ||
| 569 | + } | ||
| 570 | + entries[pattern] = entry; | ||
| 571 | + } | ||
| 572 | + | ||
| 573 | + // Helpful behavior: | ||
| 574 | + // If pattern is /tree/, insert an implicit permanent redirect for /tree. | ||
| 575 | + // It can be overridden by an explicit registration. | ||
| 576 | + if (pattern != "/" && !pattern.empty() && pattern.at(pattern.length() - 1) == '/') { | ||
| 577 | + std::string rpattern = pattern.substr(0, pattern.length() - 1); | ||
| 578 | + SrsHttpMuxEntry* entry = NULL; | ||
| 579 | + | ||
| 580 | + // free the exists not explicit entry | ||
| 581 | + if (entries.find(rpattern) != entries.end()) { | ||
| 582 | + SrsHttpMuxEntry* exists = entries[rpattern]; | ||
| 583 | + if (!exists->explicit_match) { | ||
| 584 | + entry = exists; | ||
| 585 | + } | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + // create implicit redirect. | ||
| 589 | + if (!entry || entry->explicit_match) { | ||
| 590 | + srs_freep(entry); | ||
| 591 | + | ||
| 592 | + entry = new SrsHttpMuxEntry(); | ||
| 593 | + entry->explicit_match = false; | ||
| 594 | + entry->handler = new SrsHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently); | ||
| 595 | + entry->pattern = pattern; | ||
| 596 | + entry->handler->entry = entry; | ||
| 597 | + | ||
| 598 | + entries[rpattern] = entry; | ||
| 599 | + } | ||
| 600 | + } | ||
| 601 | + | ||
| 602 | + return ret; | ||
| 603 | +} | ||
| 604 | + | ||
| 605 | +int SrsHttpServeMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) | ||
| 606 | +{ | ||
| 607 | + int ret = ERROR_SUCCESS; | ||
| 608 | + | ||
| 609 | + ISrsHttpHandler* h = NULL; | ||
| 610 | + if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) { | ||
| 611 | + srs_error("find handler failed. ret=%d", ret); | ||
| 612 | + return ret; | ||
| 613 | + } | ||
| 614 | + | ||
| 615 | + srs_assert(h); | ||
| 616 | + if ((ret = h->serve_http(w, r)) != ERROR_SUCCESS) { | ||
| 617 | + if (!srs_is_client_gracefully_close(ret)) { | ||
| 618 | + srs_error("handler serve http failed. ret=%d", ret); | ||
| 619 | + } | ||
| 620 | + return ret; | ||
| 621 | + } | ||
| 622 | + | ||
| 623 | + return ret; | ||
| 624 | +} | ||
| 625 | + | ||
| 626 | +int SrsHttpServeMux::find_handler(ISrsHttpMessage* r, ISrsHttpHandler** ph) | ||
| 627 | +{ | ||
| 628 | + int ret = ERROR_SUCCESS; | ||
| 629 | + | ||
| 630 | + // TODO: FIXME: support the path . and .. | ||
| 631 | + if (r->url().find("..") != std::string::npos) { | ||
| 632 | + ret = ERROR_HTTP_URL_NOT_CLEAN; | ||
| 633 | + srs_error("htt url not canonical, url=%s. ret=%d", r->url().c_str(), ret); | ||
| 634 | + return ret; | ||
| 635 | + } | ||
| 636 | + | ||
| 637 | + if ((ret = match(r, ph)) != ERROR_SUCCESS) { | ||
| 638 | + srs_error("http match handler failed. ret=%d", ret); | ||
| 639 | + return ret; | ||
| 640 | + } | ||
| 641 | + | ||
| 642 | + // always hijack. | ||
| 643 | + if (!hijackers.empty()) { | ||
| 644 | + // notice all hijacker the match failed. | ||
| 645 | + std::vector<ISrsHttpMatchHijacker*>::iterator it; | ||
| 646 | + for (it = hijackers.begin(); it != hijackers.end(); ++it) { | ||
| 647 | + ISrsHttpMatchHijacker* hijacker = *it; | ||
| 648 | + if ((ret = hijacker->hijack(r, ph)) != ERROR_SUCCESS) { | ||
| 649 | + srs_error("hijacker match failed. ret=%d", ret); | ||
| 650 | + return ret; | ||
| 651 | + } | ||
| 652 | + } | ||
| 653 | + } | ||
| 654 | + | ||
| 655 | + if (*ph == NULL) { | ||
| 656 | + // TODO: FIXME: memory leak. | ||
| 657 | + *ph = new SrsHttpNotFoundHandler(); | ||
| 658 | + } | ||
| 659 | + | ||
| 660 | + return ret; | ||
| 661 | +} | ||
| 662 | + | ||
| 663 | +int SrsHttpServeMux::match(ISrsHttpMessage* r, ISrsHttpHandler** ph) | ||
| 664 | +{ | ||
| 665 | + int ret = ERROR_SUCCESS; | ||
| 666 | + | ||
| 667 | + std::string path = r->path(); | ||
| 668 | + | ||
| 669 | + // Host-specific pattern takes precedence over generic ones | ||
| 670 | + if (!vhosts.empty() && vhosts.find(r->host()) != vhosts.end()) { | ||
| 671 | + path = r->host() + path; | ||
| 672 | + } | ||
| 673 | + | ||
| 674 | + int nb_matched = 0; | ||
| 675 | + ISrsHttpHandler* h = NULL; | ||
| 676 | + | ||
| 677 | + std::map<std::string, SrsHttpMuxEntry*>::iterator it; | ||
| 678 | + for (it = entries.begin(); it != entries.end(); ++it) { | ||
| 679 | + std::string pattern = it->first; | ||
| 680 | + SrsHttpMuxEntry* entry = it->second; | ||
| 681 | + | ||
| 682 | + if (!entry->enabled) { | ||
| 683 | + continue; | ||
| 684 | + } | ||
| 685 | + | ||
| 686 | + if (!path_match(pattern, path)) { | ||
| 687 | + continue; | ||
| 688 | + } | ||
| 689 | + | ||
| 690 | + if (!h || (int)pattern.length() > nb_matched) { | ||
| 691 | + nb_matched = (int)pattern.length(); | ||
| 692 | + h = entry->handler; | ||
| 693 | + } | ||
| 694 | + } | ||
| 695 | + | ||
| 696 | + *ph = h; | ||
| 697 | + | ||
| 698 | + return ret; | ||
| 699 | +} | ||
| 700 | + | ||
| 701 | +bool SrsHttpServeMux::path_match(string pattern, string path) | ||
| 702 | +{ | ||
| 703 | + if (pattern.empty()) { | ||
| 704 | + return false; | ||
| 705 | + } | ||
| 706 | + | ||
| 707 | + int n = (int)pattern.length(); | ||
| 708 | + | ||
| 709 | + // not endswith '/', exactly match. | ||
| 710 | + if (pattern.at(n - 1) != '/') { | ||
| 711 | + return pattern == path; | ||
| 712 | + } | ||
| 713 | + | ||
| 714 | + // endswith '/', match any, | ||
| 715 | + // for example, '/api/' match '/api/[N]' | ||
| 716 | + if ((int)path.length() >= n) { | ||
| 717 | + if (memcmp(pattern.data(), path.data(), n) == 0) { | ||
| 718 | + return true; | ||
| 719 | + } | ||
| 720 | + } | ||
| 721 | + | ||
| 722 | + return false; | ||
| 723 | +} | ||
| 724 | + | ||
| 725 | +ISrsHttpMessage::ISrsHttpMessage() | ||
| 726 | +{ | ||
| 727 | + _http_ts_send_buffer = new char[SRS_HTTP_TS_SEND_BUFFER_SIZE]; | ||
| 728 | +} | ||
| 729 | + | ||
| 730 | +ISrsHttpMessage::~ISrsHttpMessage() | ||
| 731 | +{ | ||
| 732 | + srs_freep(_http_ts_send_buffer); | ||
| 733 | +} | ||
| 734 | + | ||
| 735 | +char* ISrsHttpMessage::http_ts_send_buffer() | ||
| 736 | +{ | ||
| 737 | + return _http_ts_send_buffer; | ||
| 738 | +} |
| @@ -29,4 +29,466 @@ | @@ -29,4 +29,466 @@ | ||
| 29 | */ | 29 | */ |
| 30 | #include <srs_core.hpp> | 30 | #include <srs_core.hpp> |
| 31 | 31 | ||
| 32 | +#include <map> | ||
| 33 | +#include <string> | ||
| 34 | +#include <vector> | ||
| 35 | + | ||
| 36 | +class SrsFileReader; | ||
| 37 | +class SrsHttpHeader; | ||
| 38 | +class ISrsHttpMessage; | ||
| 39 | +class SrsHttpMuxEntry; | ||
| 40 | +class ISrsHttpResponseWriter; | ||
| 41 | + | ||
| 42 | +// http specification | ||
| 43 | +// CR = <US-ASCII CR, carriage return (13)> | ||
| 44 | +#define SRS_HTTP_CR SRS_CONSTS_CR // 0x0D | ||
| 45 | +// LF = <US-ASCII LF, linefeed (10)> | ||
| 46 | +#define SRS_HTTP_LF SRS_CONSTS_LF // 0x0A | ||
| 47 | +// SP = <US-ASCII SP, space (32)> | ||
| 48 | +#define SRS_HTTP_SP ' ' // 0x20 | ||
| 49 | +// HT = <US-ASCII HT, horizontal-tab (9)> | ||
| 50 | +#define SRS_HTTP_HT '\x09' // 0x09 | ||
| 51 | + | ||
| 52 | +// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all | ||
| 53 | +// protocol elements except the entity-body (see appendix 19.3 for | ||
| 54 | +// tolerant applications). | ||
| 55 | +#define SRS_HTTP_CRLF "\r\n" // 0x0D0A | ||
| 56 | +#define SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A | ||
| 57 | + | ||
| 58 | +// @see ISrsHttpMessage._http_ts_send_buffer | ||
| 59 | +#define SRS_HTTP_TS_SEND_BUFFER_SIZE 4096 | ||
| 60 | + | ||
| 61 | +// for ead all of http body, read each time. | ||
| 62 | +#define SRS_HTTP_READ_CACHE_BYTES 4096 | ||
| 63 | + | ||
| 64 | +// default http listen port. | ||
| 65 | +#define SRS_DEFAULT_HTTP_PORT 80 | ||
| 66 | + | ||
| 67 | +// for http parser macros | ||
| 68 | +#define SRS_CONSTS_HTTP_OPTIONS HTTP_OPTIONS | ||
| 69 | +#define SRS_CONSTS_HTTP_GET HTTP_GET | ||
| 70 | +#define SRS_CONSTS_HTTP_POST HTTP_POST | ||
| 71 | +#define SRS_CONSTS_HTTP_PUT HTTP_PUT | ||
| 72 | +#define SRS_CONSTS_HTTP_DELETE HTTP_DELETE | ||
| 73 | + | ||
| 74 | +// helper function: response in json format. | ||
| 75 | +extern int srs_http_response_json(ISrsHttpResponseWriter* w, std::string data); | ||
| 76 | + | ||
| 77 | +// get the status text of code. | ||
| 78 | +extern std::string srs_generate_http_status_text(int status); | ||
| 79 | + | ||
| 80 | +// bodyAllowedForStatus reports whether a given response status code | ||
| 81 | +// permits a body. See RFC2616, section 4.4. | ||
| 82 | +extern bool srs_go_http_body_allowd(int status); | ||
| 83 | + | ||
| 84 | +// DetectContentType implements the algorithm described | ||
| 85 | +// at http://mimesniff.spec.whatwg.org/ to determine the | ||
| 86 | +// Content-Type of the given data. It considers at most the | ||
| 87 | +// first 512 bytes of data. DetectContentType always returns | ||
| 88 | +// a valid MIME type: if it cannot determine a more specific one, it | ||
| 89 | +// returns "application/octet-stream". | ||
| 90 | +extern std::string srs_go_http_detect(char* data, int size); | ||
| 91 | + | ||
| 92 | +// state of message | ||
| 93 | +enum SrsHttpParseState { | ||
| 94 | + SrsHttpParseStateInit = 0, | ||
| 95 | + SrsHttpParseStateStart, | ||
| 96 | + SrsHttpParseStateHeaderComplete, | ||
| 97 | + SrsHttpParseStateMessageComplete | ||
| 98 | +}; | ||
| 99 | + | ||
| 100 | +// A Header represents the key-value pairs in an HTTP header. | ||
| 101 | +class SrsHttpHeader | ||
| 102 | +{ | ||
| 103 | +private: | ||
| 104 | + std::map<std::string, std::string> headers; | ||
| 105 | +public: | ||
| 106 | + SrsHttpHeader(); | ||
| 107 | + virtual ~SrsHttpHeader(); | ||
| 108 | +public: | ||
| 109 | + // Add adds the key, value pair to the header. | ||
| 110 | + // It appends to any existing values associated with key. | ||
| 111 | + virtual void set(std::string key, std::string value); | ||
| 112 | + // Get gets the first value associated with the given key. | ||
| 113 | + // If there are no values associated with the key, Get returns "". | ||
| 114 | + // To access multiple values of a key, access the map directly | ||
| 115 | + // with CanonicalHeaderKey. | ||
| 116 | + virtual std::string get(std::string key); | ||
| 117 | +public: | ||
| 118 | + /** | ||
| 119 | + * get the content length. -1 if not set. | ||
| 120 | + */ | ||
| 121 | + virtual int64_t content_length(); | ||
| 122 | + /** | ||
| 123 | + * set the content length by header "Content-Length" | ||
| 124 | + */ | ||
| 125 | + virtual void set_content_length(int64_t size); | ||
| 126 | +public: | ||
| 127 | + /** | ||
| 128 | + * get the content type. empty string if not set. | ||
| 129 | + */ | ||
| 130 | + virtual std::string content_type(); | ||
| 131 | + /** | ||
| 132 | + * set the content type by header "Content-Type" | ||
| 133 | + */ | ||
| 134 | + virtual void set_content_type(std::string ct); | ||
| 135 | +public: | ||
| 136 | + /** | ||
| 137 | + * write all headers to string stream. | ||
| 138 | + */ | ||
| 139 | + virtual void write(std::stringstream& ss); | ||
| 140 | +}; | ||
| 141 | + | ||
| 142 | +// A ResponseWriter interface is used by an HTTP handler to | ||
| 143 | +// construct an HTTP response. | ||
| 144 | +// Usage 1, response with specified length content: | ||
| 145 | +// ISrsHttpResponseWriter* w; // create or get response. | ||
| 146 | +// std::string msg = "Hello, HTTP!"; | ||
| 147 | +// w->header()->set_content_type("text/plain; charset=utf-8"); | ||
| 148 | +// w->header()->set_content_length(msg.length()); | ||
| 149 | +// w->write_header(SRS_CONSTS_HTTP_OK); | ||
| 150 | +// w->write((char*)msg.data(), (int)msg.length()); | ||
| 151 | +// w->final_request(); // optional flush. | ||
| 152 | +// Usage 2, response with HTTP code only, zero content length. | ||
| 153 | +// ISrsHttpResponseWriter* w; // create or get response. | ||
| 154 | +// w->header()->set_content_length(0); | ||
| 155 | +// w->write_header(SRS_CONSTS_HTTP_OK); | ||
| 156 | +// w->final_request(); | ||
| 157 | +// Usage 3, response in chunked encoding. | ||
| 158 | +// ISrsHttpResponseWriter* w; // create or get response. | ||
| 159 | +// std::string msg = "Hello, HTTP!"; | ||
| 160 | +// w->header()->set_content_type("application/octet-stream"); | ||
| 161 | +// w->write_header(SRS_CONSTS_HTTP_OK); | ||
| 162 | +// w->write((char*)msg.data(), (int)msg.length()); | ||
| 163 | +// w->write((char*)msg.data(), (int)msg.length()); | ||
| 164 | +// w->write((char*)msg.data(), (int)msg.length()); | ||
| 165 | +// w->write((char*)msg.data(), (int)msg.length()); | ||
| 166 | +// w->final_request(); // required to end the chunked and flush. | ||
| 167 | +class ISrsHttpResponseWriter | ||
| 168 | +{ | ||
| 169 | +public: | ||
| 170 | + ISrsHttpResponseWriter(); | ||
| 171 | + virtual ~ISrsHttpResponseWriter(); | ||
| 172 | +public: | ||
| 173 | + // when chunked mode, | ||
| 174 | + // final the request to complete the chunked encoding. | ||
| 175 | + // for no-chunked mode, | ||
| 176 | + // final to send request, for example, content-length is 0. | ||
| 177 | + virtual int final_request() = 0; | ||
| 178 | + | ||
| 179 | + // Header returns the header map that will be sent by WriteHeader. | ||
| 180 | + // Changing the header after a call to WriteHeader (or Write) has | ||
| 181 | + // no effect. | ||
| 182 | + virtual SrsHttpHeader* header() = 0; | ||
| 183 | + | ||
| 184 | + // Write writes the data to the connection as part of an HTTP reply. | ||
| 185 | + // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK) | ||
| 186 | + // before writing the data. If the Header does not contain a | ||
| 187 | + // Content-Type line, Write adds a Content-Type set to the result of passing | ||
| 188 | + // the initial 512 bytes of written data to DetectContentType. | ||
| 189 | + // @param data, the data to send. NULL to flush header only. | ||
| 190 | + virtual int write(char* data, int size) = 0; | ||
| 191 | + | ||
| 192 | + // WriteHeader sends an HTTP response header with status code. | ||
| 193 | + // If WriteHeader is not called explicitly, the first call to Write | ||
| 194 | + // will trigger an implicit WriteHeader(http.StatusOK). | ||
| 195 | + // Thus explicit calls to WriteHeader are mainly used to | ||
| 196 | + // send error codes. | ||
| 197 | + // @remark, user must set header then write or write_header. | ||
| 198 | + virtual void write_header(int code) = 0; | ||
| 199 | +}; | ||
| 200 | + | ||
| 201 | +/** | ||
| 202 | + * the reader interface for http response. | ||
| 203 | + */ | ||
| 204 | +class ISrsHttpResponseReader | ||
| 205 | +{ | ||
| 206 | +public: | ||
| 207 | + ISrsHttpResponseReader(); | ||
| 208 | + virtual ~ISrsHttpResponseReader(); | ||
| 209 | +public: | ||
| 210 | + /** | ||
| 211 | + * whether response read EOF. | ||
| 212 | + */ | ||
| 213 | + virtual bool eof() = 0; | ||
| 214 | + /** | ||
| 215 | + * read from the response body. | ||
| 216 | + * @param data, the buffer to read data buffer to. | ||
| 217 | + * @param nb_data, the max size of data buffer. | ||
| 218 | + * @param nb_read, the actual read size of bytes. NULL to ignore. | ||
| 219 | + * @remark when eof(), return error. | ||
| 220 | + */ | ||
| 221 | + virtual int read(char* data, int nb_data, int* nb_read) = 0; | ||
| 222 | +}; | ||
| 223 | + | ||
| 224 | +// Objects implementing the Handler interface can be | ||
| 225 | +// registered to serve a particular path or subtree | ||
| 226 | +// in the HTTP server. | ||
| 227 | +// | ||
| 228 | +// ServeHTTP should write reply headers and data to the ResponseWriter | ||
| 229 | +// and then return. Returning signals that the request is finished | ||
| 230 | +// and that the HTTP server can move on to the next request on | ||
| 231 | +// the connection. | ||
| 232 | +class ISrsHttpHandler | ||
| 233 | +{ | ||
| 234 | +public: | ||
| 235 | + SrsHttpMuxEntry* entry; | ||
| 236 | +public: | ||
| 237 | + ISrsHttpHandler(); | ||
| 238 | + virtual ~ISrsHttpHandler(); | ||
| 239 | +public: | ||
| 240 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) = 0; | ||
| 241 | +}; | ||
| 242 | + | ||
| 243 | +// Redirect to a fixed URL | ||
| 244 | +class SrsHttpRedirectHandler : public ISrsHttpHandler | ||
| 245 | +{ | ||
| 246 | +private: | ||
| 247 | + std::string url; | ||
| 248 | + int code; | ||
| 249 | +public: | ||
| 250 | + SrsHttpRedirectHandler(std::string u, int c); | ||
| 251 | + virtual ~SrsHttpRedirectHandler(); | ||
| 252 | +public: | ||
| 253 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); | ||
| 254 | +}; | ||
| 255 | + | ||
| 256 | +// NotFound replies to the request with an HTTP 404 not found error. | ||
| 257 | +class SrsHttpNotFoundHandler : public ISrsHttpHandler | ||
| 258 | +{ | ||
| 259 | +public: | ||
| 260 | + SrsHttpNotFoundHandler(); | ||
| 261 | + virtual ~SrsHttpNotFoundHandler(); | ||
| 262 | +public: | ||
| 263 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); | ||
| 264 | +}; | ||
| 265 | + | ||
| 266 | +// FileServer returns a handler that serves HTTP requests | ||
| 267 | +// with the contents of the file system rooted at root. | ||
| 268 | +// | ||
| 269 | +// To use the operating system's file system implementation, | ||
| 270 | +// use http.Dir: | ||
| 271 | +// | ||
| 272 | +// http.Handle("/", SrsHttpFileServer("/tmp")) | ||
| 273 | +// http.Handle("/", SrsHttpFileServer("static-dir")) | ||
| 274 | +class SrsHttpFileServer : public ISrsHttpHandler | ||
| 275 | +{ | ||
| 276 | +protected: | ||
| 277 | + std::string dir; | ||
| 278 | +public: | ||
| 279 | + SrsHttpFileServer(std::string root_dir); | ||
| 280 | + virtual ~SrsHttpFileServer(); | ||
| 281 | +public: | ||
| 282 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); | ||
| 283 | +private: | ||
| 284 | + /** | ||
| 285 | + * serve the file by specified path | ||
| 286 | + */ | ||
| 287 | + virtual int serve_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath); | ||
| 288 | + virtual int serve_flv_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath); | ||
| 289 | + virtual int serve_mp4_file(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath); | ||
| 290 | +protected: | ||
| 291 | + /** | ||
| 292 | + * when access flv file with x.flv?start=xxx | ||
| 293 | + */ | ||
| 294 | + virtual int serve_flv_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int offset); | ||
| 295 | + /** | ||
| 296 | + * when access mp4 file with x.mp4?range=start-end | ||
| 297 | + * @param start the start offset in bytes. | ||
| 298 | + * @param end the end offset in bytes. -1 to end of file. | ||
| 299 | + * @remark response data in [start, end]. | ||
| 300 | + */ | ||
| 301 | + virtual int serve_mp4_stream(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, std::string fullpath, int start, int end); | ||
| 302 | +protected: | ||
| 303 | + /** | ||
| 304 | + * copy the fs to response writer in size bytes. | ||
| 305 | + */ | ||
| 306 | + virtual int copy(ISrsHttpResponseWriter* w, SrsFileReader* fs, ISrsHttpMessage* r, int size); | ||
| 307 | +}; | ||
| 308 | + | ||
| 309 | +// the mux entry for server mux. | ||
| 310 | +// the matcher info, for example, the pattern and handler. | ||
| 311 | +class SrsHttpMuxEntry | ||
| 312 | +{ | ||
| 313 | +public: | ||
| 314 | + bool explicit_match; | ||
| 315 | + ISrsHttpHandler* handler; | ||
| 316 | + std::string pattern; | ||
| 317 | + bool enabled; | ||
| 318 | +public: | ||
| 319 | + SrsHttpMuxEntry(); | ||
| 320 | + virtual ~SrsHttpMuxEntry(); | ||
| 321 | +}; | ||
| 322 | + | ||
| 323 | +/** | ||
| 324 | + * the hijacker for http pattern match. | ||
| 325 | + */ | ||
| 326 | +class ISrsHttpMatchHijacker | ||
| 327 | +{ | ||
| 328 | +public: | ||
| 329 | + ISrsHttpMatchHijacker(); | ||
| 330 | + virtual ~ISrsHttpMatchHijacker(); | ||
| 331 | +public: | ||
| 332 | + /** | ||
| 333 | + * when match the request failed, no handler to process request. | ||
| 334 | + * @param request the http request message to match the handler. | ||
| 335 | + * @param ph the already matched handler, hijack can rewrite it. | ||
| 336 | + */ | ||
| 337 | + virtual int hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) = 0; | ||
| 338 | +}; | ||
| 339 | + | ||
| 340 | +// ServeMux is an HTTP request multiplexer. | ||
| 341 | +// It matches the URL of each incoming request against a list of registered | ||
| 342 | +// patterns and calls the handler for the pattern that | ||
| 343 | +// most closely matches the URL. | ||
| 344 | +// | ||
| 345 | +// Patterns name fixed, rooted paths, like "/favicon.ico", | ||
| 346 | +// or rooted subtrees, like "/images/" (note the trailing slash). | ||
| 347 | +// Longer patterns take precedence over shorter ones, so that | ||
| 348 | +// if there are handlers registered for both "/images/" | ||
| 349 | +// and "/images/thumbnails/", the latter handler will be | ||
| 350 | +// called for paths beginning "/images/thumbnails/" and the | ||
| 351 | +// former will receive requests for any other paths in the | ||
| 352 | +// "/images/" subtree. | ||
| 353 | +// | ||
| 354 | +// Note that since a pattern ending in a slash names a rooted subtree, | ||
| 355 | +// the pattern "/" matches all paths not matched by other registered | ||
| 356 | +// patterns, not just the URL with Path == "/". | ||
| 357 | +// | ||
| 358 | +// Patterns may optionally begin with a host name, restricting matches to | ||
| 359 | +// URLs on that host only. Host-specific patterns take precedence over | ||
| 360 | +// general patterns, so that a handler might register for the two patterns | ||
| 361 | +// "/codesearch" and "codesearch.google.com/" without also taking over | ||
| 362 | +// requests for "http://www.google.com/". | ||
| 363 | +// | ||
| 364 | +// ServeMux also takes care of sanitizing the URL request path, | ||
| 365 | +// redirecting any request containing . or .. elements to an | ||
| 366 | +// equivalent .- and ..-free URL. | ||
| 367 | +class SrsHttpServeMux | ||
| 368 | +{ | ||
| 369 | +private: | ||
| 370 | + // the pattern handler, to handle the http request. | ||
| 371 | + std::map<std::string, SrsHttpMuxEntry*> entries; | ||
| 372 | + // the vhost handler. | ||
| 373 | + // when find the handler to process the request, | ||
| 374 | + // append the matched vhost when pattern not starts with /, | ||
| 375 | + // for example, for pattern /live/livestream.flv of vhost ossrs.net, | ||
| 376 | + // the path will rewrite to ossrs.net/live/livestream.flv | ||
| 377 | + std::map<std::string, ISrsHttpHandler*> vhosts; | ||
| 378 | + // all hijackers for http match. | ||
| 379 | + // for example, the hstrs(http stream trigger rtmp source) | ||
| 380 | + // can hijack and install handler when request incoming and no handler. | ||
| 381 | + std::vector<ISrsHttpMatchHijacker*> hijackers; | ||
| 382 | +public: | ||
| 383 | + SrsHttpServeMux(); | ||
| 384 | + virtual ~SrsHttpServeMux(); | ||
| 385 | +public: | ||
| 386 | + /** | ||
| 387 | + * initialize the http serve mux. | ||
| 388 | + */ | ||
| 389 | + virtual int initialize(); | ||
| 390 | + /** | ||
| 391 | + * hijack the http match. | ||
| 392 | + */ | ||
| 393 | + virtual void hijack(ISrsHttpMatchHijacker* h); | ||
| 394 | + virtual void unhijack(ISrsHttpMatchHijacker* h); | ||
| 395 | +public: | ||
| 396 | + // Handle registers the handler for the given pattern. | ||
| 397 | + // If a handler already exists for pattern, Handle panics. | ||
| 398 | + virtual int handle(std::string pattern, ISrsHttpHandler* handler); | ||
| 399 | + // interface ISrsHttpHandler | ||
| 400 | +public: | ||
| 401 | + virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); | ||
| 402 | +private: | ||
| 403 | + virtual int find_handler(ISrsHttpMessage* r, ISrsHttpHandler** ph); | ||
| 404 | + virtual int match(ISrsHttpMessage* r, ISrsHttpHandler** ph); | ||
| 405 | + virtual bool path_match(std::string pattern, std::string path); | ||
| 406 | +}; | ||
| 407 | + | ||
| 408 | +// for http header. | ||
| 409 | +typedef std::pair<std::string, std::string> SrsHttpHeaderField; | ||
| 410 | + | ||
| 411 | +// A Request represents an HTTP request received by a server | ||
| 412 | +// or to be sent by a client. | ||
| 413 | +// | ||
| 414 | +// The field semantics differ slightly between client and server | ||
| 415 | +// usage. In addition to the notes on the fields below, see the | ||
| 416 | +// documentation for Request.Write and RoundTripper. | ||
| 417 | +/** | ||
| 418 | + * the http message, request or response. | ||
| 419 | + */ | ||
| 420 | +class ISrsHttpMessage | ||
| 421 | +{ | ||
| 422 | +private: | ||
| 423 | + /** | ||
| 424 | + * use a buffer to read and send ts file. | ||
| 425 | + */ | ||
| 426 | + // TODO: FIXME: remove it. | ||
| 427 | + char* _http_ts_send_buffer; | ||
| 428 | +public: | ||
| 429 | + ISrsHttpMessage(); | ||
| 430 | + virtual ~ISrsHttpMessage(); | ||
| 431 | +public: | ||
| 432 | + /** | ||
| 433 | + * the http request level cache. | ||
| 434 | + */ | ||
| 435 | + virtual char* http_ts_send_buffer(); | ||
| 436 | +public: | ||
| 437 | + virtual u_int8_t method() = 0; | ||
| 438 | + virtual u_int16_t status_code() = 0; | ||
| 439 | + /** | ||
| 440 | + * method helpers. | ||
| 441 | + */ | ||
| 442 | + virtual std::string method_str() = 0; | ||
| 443 | + virtual bool is_http_get() = 0; | ||
| 444 | + virtual bool is_http_put() = 0; | ||
| 445 | + virtual bool is_http_post() = 0; | ||
| 446 | + virtual bool is_http_delete() = 0; | ||
| 447 | + virtual bool is_http_options() = 0; | ||
| 448 | +public: | ||
| 449 | + /** | ||
| 450 | + * whether should keep the connection alive. | ||
| 451 | + */ | ||
| 452 | + virtual bool is_keep_alive() = 0; | ||
| 453 | + /** | ||
| 454 | + * the uri contains the host and path. | ||
| 455 | + */ | ||
| 456 | + virtual std::string uri() = 0; | ||
| 457 | + /** | ||
| 458 | + * the url maybe the path. | ||
| 459 | + */ | ||
| 460 | + virtual std::string url() = 0; | ||
| 461 | + virtual std::string host() = 0; | ||
| 462 | + virtual std::string path() = 0; | ||
| 463 | + virtual std::string ext() = 0; | ||
| 464 | +public: | ||
| 465 | + /** | ||
| 466 | + * read body to string. | ||
| 467 | + * @remark for small http body. | ||
| 468 | + */ | ||
| 469 | + virtual int body_read_all(std::string& body) = 0; | ||
| 470 | + /** | ||
| 471 | + * get the body reader, to read one by one. | ||
| 472 | + * @remark when body is very large, or chunked, use this. | ||
| 473 | + */ | ||
| 474 | + virtual ISrsHttpResponseReader* body_reader() = 0; | ||
| 475 | + /** | ||
| 476 | + * the content length, -1 for chunked or not set. | ||
| 477 | + */ | ||
| 478 | + virtual int64_t content_length() = 0; | ||
| 479 | +public: | ||
| 480 | + /** | ||
| 481 | + * get the param in query string, | ||
| 482 | + * for instance, query is "start=100&end=200", | ||
| 483 | + * then query_get("start") is "100", and query_get("end") is "200" | ||
| 484 | + */ | ||
| 485 | + virtual std::string query_get(std::string key) = 0; | ||
| 486 | + /** | ||
| 487 | + * get the headers. | ||
| 488 | + */ | ||
| 489 | + virtual int request_header_count() = 0; | ||
| 490 | + virtual std::string request_header_key_at(int index) = 0; | ||
| 491 | + virtual std::string request_header_value_at(int index) = 0; | ||
| 492 | +}; | ||
| 493 | + | ||
| 32 | #endif | 494 | #endif |
-
请 注册 或 登录 后发表评论