for bug #277, refine http api refer to go http-framework. 2.0.97
正在显示
10 个修改的文件
包含
1001 行增加
和
392 行删除
| @@ -510,6 +510,7 @@ Supported operating systems and hardware: | @@ -510,6 +510,7 @@ Supported operating systems and hardware: | ||
| 510 | 510 | ||
| 511 | ## History | 511 | ## History |
| 512 | 512 | ||
| 513 | +* v2.0, 2015-01-17, for [#277](https://github.com/winlinvip/simple-rtmp-server/issues/277), refine http api refer to go http-framework. 2.0.97 | ||
| 513 | * v2.0, 2015-01-17, hotfix [#290](https://github.com/winlinvip/simple-rtmp-server/issues/290), use iformat only for rtmp input. 2.0.95 | 514 | * v2.0, 2015-01-17, hotfix [#290](https://github.com/winlinvip/simple-rtmp-server/issues/290), use iformat only for rtmp input. 2.0.95 |
| 514 | * v2.0, 2015-01-08, hotfix [#281](https://github.com/winlinvip/simple-rtmp-server/issues/281), fix hls bug ignore type-9 send aud. 2.0.93 | 515 | * v2.0, 2015-01-08, hotfix [#281](https://github.com/winlinvip/simple-rtmp-server/issues/281), fix hls bug ignore type-9 send aud. 2.0.93 |
| 515 | * v2.0, 2015-01-03, fix [#274](https://github.com/winlinvip/simple-rtmp-server/issues/274), http-callback support on_dvr when reap a dvr file. 2.0.89 | 516 | * v2.0, 2015-01-03, fix [#274](https://github.com/winlinvip/simple-rtmp-server/issues/274), http-callback support on_dvr when reap a dvr file. 2.0.89 |
| @@ -68,6 +68,503 @@ bool srs_path_like(const char* expect, const char* path, int nb_path) | @@ -68,6 +68,503 @@ bool srs_path_like(const char* expect, const char* path, int nb_path) | ||
| 68 | return equals; | 68 | return equals; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | +int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data) | ||
| 72 | +{ | ||
| 73 | + w->header()->set_content_length(data.length()); | ||
| 74 | + w->header()->set_content_type("application/json;charset=utf-8"); | ||
| 75 | + | ||
| 76 | + return w->write((char*)data.data(), data.length()); | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +// get the status text of code. | ||
| 80 | +string srs_generate_status_text(int status) | ||
| 81 | +{ | ||
| 82 | + static std::map<int, std::string> _status_map; | ||
| 83 | + if (_status_map.empty()) { | ||
| 84 | + _status_map[SRS_CONSTS_HTTP_Continue ] = SRS_CONSTS_HTTP_Continue_str ; | ||
| 85 | + _status_map[SRS_CONSTS_HTTP_SwitchingProtocols ] = SRS_CONSTS_HTTP_SwitchingProtocols_str ; | ||
| 86 | + _status_map[SRS_CONSTS_HTTP_OK ] = SRS_CONSTS_HTTP_OK_str ; | ||
| 87 | + _status_map[SRS_CONSTS_HTTP_Created ] = SRS_CONSTS_HTTP_Created_str ; | ||
| 88 | + _status_map[SRS_CONSTS_HTTP_Accepted ] = SRS_CONSTS_HTTP_Accepted_str ; | ||
| 89 | + _status_map[SRS_CONSTS_HTTP_NonAuthoritativeInformation ] = SRS_CONSTS_HTTP_NonAuthoritativeInformation_str ; | ||
| 90 | + _status_map[SRS_CONSTS_HTTP_NoContent ] = SRS_CONSTS_HTTP_NoContent_str ; | ||
| 91 | + _status_map[SRS_CONSTS_HTTP_ResetContent ] = SRS_CONSTS_HTTP_ResetContent_str ; | ||
| 92 | + _status_map[SRS_CONSTS_HTTP_PartialContent ] = SRS_CONSTS_HTTP_PartialContent_str ; | ||
| 93 | + _status_map[SRS_CONSTS_HTTP_MultipleChoices ] = SRS_CONSTS_HTTP_MultipleChoices_str ; | ||
| 94 | + _status_map[SRS_CONSTS_HTTP_MovedPermanently ] = SRS_CONSTS_HTTP_MovedPermanently_str ; | ||
| 95 | + _status_map[SRS_CONSTS_HTTP_Found ] = SRS_CONSTS_HTTP_Found_str ; | ||
| 96 | + _status_map[SRS_CONSTS_HTTP_SeeOther ] = SRS_CONSTS_HTTP_SeeOther_str ; | ||
| 97 | + _status_map[SRS_CONSTS_HTTP_NotModified ] = SRS_CONSTS_HTTP_NotModified_str ; | ||
| 98 | + _status_map[SRS_CONSTS_HTTP_UseProxy ] = SRS_CONSTS_HTTP_UseProxy_str ; | ||
| 99 | + _status_map[SRS_CONSTS_HTTP_TemporaryRedirect ] = SRS_CONSTS_HTTP_TemporaryRedirect_str ; | ||
| 100 | + _status_map[SRS_CONSTS_HTTP_BadRequest ] = SRS_CONSTS_HTTP_BadRequest_str ; | ||
| 101 | + _status_map[SRS_CONSTS_HTTP_Unauthorized ] = SRS_CONSTS_HTTP_Unauthorized_str ; | ||
| 102 | + _status_map[SRS_CONSTS_HTTP_PaymentRequired ] = SRS_CONSTS_HTTP_PaymentRequired_str ; | ||
| 103 | + _status_map[SRS_CONSTS_HTTP_Forbidden ] = SRS_CONSTS_HTTP_Forbidden_str ; | ||
| 104 | + _status_map[SRS_CONSTS_HTTP_NotFound ] = SRS_CONSTS_HTTP_NotFound_str ; | ||
| 105 | + _status_map[SRS_CONSTS_HTTP_MethodNotAllowed ] = SRS_CONSTS_HTTP_MethodNotAllowed_str ; | ||
| 106 | + _status_map[SRS_CONSTS_HTTP_NotAcceptable ] = SRS_CONSTS_HTTP_NotAcceptable_str ; | ||
| 107 | + _status_map[SRS_CONSTS_HTTP_ProxyAuthenticationRequired ] = SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str ; | ||
| 108 | + _status_map[SRS_CONSTS_HTTP_RequestTimeout ] = SRS_CONSTS_HTTP_RequestTimeout_str ; | ||
| 109 | + _status_map[SRS_CONSTS_HTTP_Conflict ] = SRS_CONSTS_HTTP_Conflict_str ; | ||
| 110 | + _status_map[SRS_CONSTS_HTTP_Gone ] = SRS_CONSTS_HTTP_Gone_str ; | ||
| 111 | + _status_map[SRS_CONSTS_HTTP_LengthRequired ] = SRS_CONSTS_HTTP_LengthRequired_str ; | ||
| 112 | + _status_map[SRS_CONSTS_HTTP_PreconditionFailed ] = SRS_CONSTS_HTTP_PreconditionFailed_str ; | ||
| 113 | + _status_map[SRS_CONSTS_HTTP_RequestEntityTooLarge ] = SRS_CONSTS_HTTP_RequestEntityTooLarge_str ; | ||
| 114 | + _status_map[SRS_CONSTS_HTTP_RequestURITooLarge ] = SRS_CONSTS_HTTP_RequestURITooLarge_str ; | ||
| 115 | + _status_map[SRS_CONSTS_HTTP_UnsupportedMediaType ] = SRS_CONSTS_HTTP_UnsupportedMediaType_str ; | ||
| 116 | + _status_map[SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable ] = SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str ; | ||
| 117 | + _status_map[SRS_CONSTS_HTTP_ExpectationFailed ] = SRS_CONSTS_HTTP_ExpectationFailed_str ; | ||
| 118 | + _status_map[SRS_CONSTS_HTTP_InternalServerError ] = SRS_CONSTS_HTTP_InternalServerError_str ; | ||
| 119 | + _status_map[SRS_CONSTS_HTTP_NotImplemented ] = SRS_CONSTS_HTTP_NotImplemented_str ; | ||
| 120 | + _status_map[SRS_CONSTS_HTTP_BadGateway ] = SRS_CONSTS_HTTP_BadGateway_str ; | ||
| 121 | + _status_map[SRS_CONSTS_HTTP_ServiceUnavailable ] = SRS_CONSTS_HTTP_ServiceUnavailable_str ; | ||
| 122 | + _status_map[SRS_CONSTS_HTTP_GatewayTimeout ] = SRS_CONSTS_HTTP_GatewayTimeout_str ; | ||
| 123 | + _status_map[SRS_CONSTS_HTTP_HTTPVersionNotSupported ] = SRS_CONSTS_HTTP_HTTPVersionNotSupported_str ; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + std::string status_text; | ||
| 127 | + if (_status_map.find(status) == _status_map.end()) { | ||
| 128 | + status_text = "Status Unknown"; | ||
| 129 | + } else { | ||
| 130 | + status_text = _status_map[status]; | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + return status_text; | ||
| 134 | +} | ||
| 135 | + | ||
| 136 | +// bodyAllowedForStatus reports whether a given response status code | ||
| 137 | +// permits a body. See RFC2616, section 4.4. | ||
| 138 | +bool srs_go_http_body_allowd(int status) | ||
| 139 | +{ | ||
| 140 | + if (status >= 100 && status <= 199) { | ||
| 141 | + return false; | ||
| 142 | + } else if (status == 204 || status == 304) { | ||
| 143 | + return false; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + return true; | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +// DetectContentType implements the algorithm described | ||
| 150 | +// at http://mimesniff.spec.whatwg.org/ to determine the | ||
| 151 | +// Content-Type of the given data. It considers at most the | ||
| 152 | +// first 512 bytes of data. DetectContentType always returns | ||
| 153 | +// a valid MIME type: if it cannot determine a more specific one, it | ||
| 154 | +// returns "application/octet-stream". | ||
| 155 | +string srs_go_http_detect(char* data, int size) | ||
| 156 | +{ | ||
| 157 | + return "application/octet-stream"; // fallback | ||
| 158 | +} | ||
| 159 | + | ||
| 160 | +// Error replies to the request with the specified error message and HTTP code. | ||
| 161 | +// The error message should be plain text. | ||
| 162 | +int srs_go_http_error(ISrsGoHttpResponseWriter* w, int code, string error) | ||
| 163 | +{ | ||
| 164 | + int ret = ERROR_SUCCESS; | ||
| 165 | + | ||
| 166 | + w->header()->set_content_type("text/plain; charset=utf-8"); | ||
| 167 | + w->header()->set_content_length(error.length()); | ||
| 168 | + w->write_header(code); | ||
| 169 | + w->write((char*)error.data(), (int)error.length()); | ||
| 170 | + | ||
| 171 | + return ret; | ||
| 172 | +} | ||
| 173 | + | ||
| 174 | +SrsGoHttpHeader::SrsGoHttpHeader() | ||
| 175 | +{ | ||
| 176 | +} | ||
| 177 | + | ||
| 178 | +SrsGoHttpHeader::~SrsGoHttpHeader() | ||
| 179 | +{ | ||
| 180 | +} | ||
| 181 | + | ||
| 182 | +void SrsGoHttpHeader::set(string key, string value) | ||
| 183 | +{ | ||
| 184 | + headers[key] = value; | ||
| 185 | +} | ||
| 186 | + | ||
| 187 | +string SrsGoHttpHeader::get(string key) | ||
| 188 | +{ | ||
| 189 | + std::string v; | ||
| 190 | + | ||
| 191 | + if (headers.find(key) != headers.end()) { | ||
| 192 | + v = headers[key]; | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + return v; | ||
| 196 | +} | ||
| 197 | + | ||
| 198 | +int64_t SrsGoHttpHeader::content_length() | ||
| 199 | +{ | ||
| 200 | + std::string cl = get("Content-Length"); | ||
| 201 | + | ||
| 202 | + if (cl.empty()) { | ||
| 203 | + return -1; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + return (int64_t)::atof(cl.c_str()); | ||
| 207 | +} | ||
| 208 | + | ||
| 209 | +void SrsGoHttpHeader::set_content_length(int64_t size) | ||
| 210 | +{ | ||
| 211 | + char buf[64]; | ||
| 212 | + snprintf(buf, sizeof(buf), "%"PRId64, size); | ||
| 213 | + set("Content-Length", buf); | ||
| 214 | +} | ||
| 215 | + | ||
| 216 | +string SrsGoHttpHeader::content_type() | ||
| 217 | +{ | ||
| 218 | + return get("Content-Type"); | ||
| 219 | +} | ||
| 220 | + | ||
| 221 | +void SrsGoHttpHeader::set_content_type(string ct) | ||
| 222 | +{ | ||
| 223 | + set("Content-Type", ct); | ||
| 224 | +} | ||
| 225 | + | ||
| 226 | +void SrsGoHttpHeader::write(stringstream& ss) | ||
| 227 | +{ | ||
| 228 | + std::map<std::string, std::string>::iterator it; | ||
| 229 | + for (it = headers.begin(); it != headers.end(); ++it) { | ||
| 230 | + ss << it->first << ": " << it->second << __SRS_CRLF; | ||
| 231 | + } | ||
| 232 | +} | ||
| 233 | + | ||
| 234 | +ISrsGoHttpResponseWriter::ISrsGoHttpResponseWriter() | ||
| 235 | +{ | ||
| 236 | +} | ||
| 237 | + | ||
| 238 | +ISrsGoHttpResponseWriter::~ISrsGoHttpResponseWriter() | ||
| 239 | +{ | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +ISrsGoHttpHandler::ISrsGoHttpHandler() | ||
| 243 | +{ | ||
| 244 | +} | ||
| 245 | + | ||
| 246 | +ISrsGoHttpHandler::~ISrsGoHttpHandler() | ||
| 247 | +{ | ||
| 248 | +} | ||
| 249 | + | ||
| 250 | +SrsGoHttpRedirectHandler::SrsGoHttpRedirectHandler(string u, int c) | ||
| 251 | +{ | ||
| 252 | + url = u; | ||
| 253 | + code = c; | ||
| 254 | +} | ||
| 255 | + | ||
| 256 | +SrsGoHttpRedirectHandler::~SrsGoHttpRedirectHandler() | ||
| 257 | +{ | ||
| 258 | +} | ||
| 259 | + | ||
| 260 | +int SrsGoHttpRedirectHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 261 | +{ | ||
| 262 | + int ret = ERROR_SUCCESS; | ||
| 263 | + // TODO: FIXME: implements it. | ||
| 264 | + return ret; | ||
| 265 | +} | ||
| 266 | + | ||
| 267 | +SrsGoHttpNotFoundHandler::SrsGoHttpNotFoundHandler() | ||
| 268 | +{ | ||
| 269 | +} | ||
| 270 | + | ||
| 271 | +SrsGoHttpNotFoundHandler::~SrsGoHttpNotFoundHandler() | ||
| 272 | +{ | ||
| 273 | +} | ||
| 274 | + | ||
| 275 | +int SrsGoHttpNotFoundHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 276 | +{ | ||
| 277 | + return srs_go_http_error(w, | ||
| 278 | + SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str); | ||
| 279 | +} | ||
| 280 | + | ||
| 281 | +SrsGoHttpMuxEntry::SrsGoHttpMuxEntry() | ||
| 282 | +{ | ||
| 283 | + explicit_match = false; | ||
| 284 | + handler = NULL; | ||
| 285 | +} | ||
| 286 | + | ||
| 287 | +SrsGoHttpMuxEntry::~SrsGoHttpMuxEntry() | ||
| 288 | +{ | ||
| 289 | + srs_freep(handler); | ||
| 290 | +} | ||
| 291 | + | ||
| 292 | +SrsGoHttpServeMux::SrsGoHttpServeMux() | ||
| 293 | +{ | ||
| 294 | +} | ||
| 295 | + | ||
| 296 | +SrsGoHttpServeMux::~SrsGoHttpServeMux() | ||
| 297 | +{ | ||
| 298 | + std::map<std::string, SrsGoHttpMuxEntry*>::iterator it; | ||
| 299 | + for (it = entries.begin(); it != entries.end(); ++it) { | ||
| 300 | + SrsGoHttpMuxEntry* entry = it->second; | ||
| 301 | + srs_freep(entry); | ||
| 302 | + } | ||
| 303 | + entries.clear(); | ||
| 304 | +} | ||
| 305 | + | ||
| 306 | +int SrsGoHttpServeMux::initialize() | ||
| 307 | +{ | ||
| 308 | + int ret = ERROR_SUCCESS; | ||
| 309 | + // TODO: FIXME: implements it. | ||
| 310 | + return ret; | ||
| 311 | +} | ||
| 312 | + | ||
| 313 | +int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler) | ||
| 314 | +{ | ||
| 315 | + int ret = ERROR_SUCCESS; | ||
| 316 | + | ||
| 317 | + srs_assert(handler); | ||
| 318 | + | ||
| 319 | + if (pattern.empty()) { | ||
| 320 | + ret = ERROR_HTTP_PATTERN_EMPTY; | ||
| 321 | + srs_error("http: empty pattern. ret=%d", ret); | ||
| 322 | + return ret; | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + if (entries.find(pattern) != entries.end()) { | ||
| 326 | + SrsGoHttpMuxEntry* exists = entries[pattern]; | ||
| 327 | + if (exists->explicit_match) { | ||
| 328 | + ret = ERROR_HTTP_PATTERN_DUPLICATED; | ||
| 329 | + srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret); | ||
| 330 | + return ret; | ||
| 331 | + } | ||
| 332 | + } | ||
| 333 | + | ||
| 334 | + if (true) { | ||
| 335 | + SrsGoHttpMuxEntry* entry = new SrsGoHttpMuxEntry(); | ||
| 336 | + entry->explicit_match = true; | ||
| 337 | + entry->handler = handler; | ||
| 338 | + entry->pattern = pattern; | ||
| 339 | + | ||
| 340 | + if (entries.find(pattern) != entries.end()) { | ||
| 341 | + SrsGoHttpMuxEntry* exists = entries[pattern]; | ||
| 342 | + srs_freep(exists); | ||
| 343 | + } | ||
| 344 | + entries[pattern] = entry; | ||
| 345 | + } | ||
| 346 | + | ||
| 347 | + // Helpful behavior: | ||
| 348 | + // If pattern is /tree/, insert an implicit permanent redirect for /tree. | ||
| 349 | + // It can be overridden by an explicit registration. | ||
| 350 | + if (!pattern.empty() && pattern.at(pattern.length() - 1) == '/') { | ||
| 351 | + std::string rpattern = pattern.substr(0, pattern.length() - 1); | ||
| 352 | + SrsGoHttpMuxEntry* entry = NULL; | ||
| 353 | + | ||
| 354 | + // free the exists not explicit entry | ||
| 355 | + if (entries.find(rpattern) != entries.end()) { | ||
| 356 | + SrsGoHttpMuxEntry* exists = entries[rpattern]; | ||
| 357 | + if (!exists->explicit_match) { | ||
| 358 | + entry = exists; | ||
| 359 | + } | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + // create implicit redirect. | ||
| 363 | + if (!entry || entry->explicit_match) { | ||
| 364 | + srs_freep(entry); | ||
| 365 | + | ||
| 366 | + entry = new SrsGoHttpMuxEntry(); | ||
| 367 | + entry->explicit_match = false; | ||
| 368 | + entry->handler = new SrsGoHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently); | ||
| 369 | + entry->pattern = pattern; | ||
| 370 | + | ||
| 371 | + entries[rpattern] = entry; | ||
| 372 | + } | ||
| 373 | + } | ||
| 374 | + | ||
| 375 | + return ret; | ||
| 376 | +} | ||
| 377 | + | ||
| 378 | +int SrsGoHttpServeMux::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 379 | +{ | ||
| 380 | + int ret = ERROR_SUCCESS; | ||
| 381 | + | ||
| 382 | + ISrsGoHttpHandler* h = NULL; | ||
| 383 | + if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) { | ||
| 384 | + srs_error("find handler failed. ret=%d", ret); | ||
| 385 | + return ret; | ||
| 386 | + } | ||
| 387 | + | ||
| 388 | + srs_assert(h); | ||
| 389 | + if ((ret = h->serve_http(w, r)) != ERROR_SUCCESS) { | ||
| 390 | + srs_error("handler serve http failed. ret=%d", ret); | ||
| 391 | + return ret; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + return ret; | ||
| 395 | +} | ||
| 396 | + | ||
| 397 | +int SrsGoHttpServeMux::find_handler(SrsHttpMessage* r, ISrsGoHttpHandler** ph) | ||
| 398 | +{ | ||
| 399 | + int ret = ERROR_SUCCESS; | ||
| 400 | + | ||
| 401 | + // TODO: FIXME: support the path . and .. | ||
| 402 | + if (r->url().find("..") != std::string::npos) { | ||
| 403 | + ret = ERROR_HTTP_URL_NOT_CLEAN; | ||
| 404 | + srs_error("htt url not canonical, url=%s. ret=%d", r->url().c_str(), ret); | ||
| 405 | + return ret; | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + if ((ret = match(r, ph)) != ERROR_SUCCESS) { | ||
| 409 | + srs_error("http match handler failed. ret=%d", ret); | ||
| 410 | + return ret; | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + if (*ph == NULL) { | ||
| 414 | + *ph = new SrsGoHttpNotFoundHandler(); | ||
| 415 | + } | ||
| 416 | + | ||
| 417 | + return ret; | ||
| 418 | +} | ||
| 419 | + | ||
| 420 | +int SrsGoHttpServeMux::match(SrsHttpMessage* r, ISrsGoHttpHandler** ph) | ||
| 421 | +{ | ||
| 422 | + int ret = ERROR_SUCCESS; | ||
| 423 | + | ||
| 424 | + std::string path = r->path(); | ||
| 425 | + | ||
| 426 | + int nb_matched = 0; | ||
| 427 | + ISrsGoHttpHandler* h = NULL; | ||
| 428 | + | ||
| 429 | + std::map<std::string, SrsGoHttpMuxEntry*>::iterator it; | ||
| 430 | + for (it = entries.begin(); it != entries.end(); ++it) { | ||
| 431 | + std::string pattern = it->first; | ||
| 432 | + SrsGoHttpMuxEntry* entry = it->second; | ||
| 433 | + | ||
| 434 | + if (!path_match(pattern, path)) { | ||
| 435 | + continue; | ||
| 436 | + } | ||
| 437 | + | ||
| 438 | + if (!h || (int)pattern.length() > nb_matched) { | ||
| 439 | + nb_matched = (int)pattern.length(); | ||
| 440 | + h = entry->handler; | ||
| 441 | + } | ||
| 442 | + } | ||
| 443 | + | ||
| 444 | + *ph = h; | ||
| 445 | + | ||
| 446 | + return ret; | ||
| 447 | +} | ||
| 448 | + | ||
| 449 | +bool SrsGoHttpServeMux::path_match(string pattern, string path) | ||
| 450 | +{ | ||
| 451 | + if (pattern.empty()) { | ||
| 452 | + return false; | ||
| 453 | + } | ||
| 454 | + | ||
| 455 | + int n = pattern.length(); | ||
| 456 | + | ||
| 457 | + // not endswith '/', exactly match. | ||
| 458 | + if (pattern.at(n - 1) != '/') { | ||
| 459 | + return pattern == path; | ||
| 460 | + } | ||
| 461 | + | ||
| 462 | + // endswith '/', match any, | ||
| 463 | + // for example, '/api/' match '/api/[N]' | ||
| 464 | + if ((int)path.length() >= n) { | ||
| 465 | + if (memcmp(pattern.data(), path.data(), n) == 0) { | ||
| 466 | + return true; | ||
| 467 | + } | ||
| 468 | + } | ||
| 469 | + | ||
| 470 | + return false; | ||
| 471 | +} | ||
| 472 | + | ||
| 473 | +SrsGoHttpResponseWriter::SrsGoHttpResponseWriter(SrsStSocket* io) | ||
| 474 | +{ | ||
| 475 | + skt = io; | ||
| 476 | + hdr = new SrsGoHttpHeader(); | ||
| 477 | + header_wrote = false; | ||
| 478 | + status = SRS_CONSTS_HTTP_OK; | ||
| 479 | + content_length = -1; | ||
| 480 | + written = 0; | ||
| 481 | + header_sent = false; | ||
| 482 | +} | ||
| 483 | + | ||
| 484 | +SrsGoHttpResponseWriter::~SrsGoHttpResponseWriter() | ||
| 485 | +{ | ||
| 486 | + srs_freep(hdr); | ||
| 487 | +} | ||
| 488 | + | ||
| 489 | +SrsGoHttpHeader* SrsGoHttpResponseWriter::header() | ||
| 490 | +{ | ||
| 491 | + return hdr; | ||
| 492 | +} | ||
| 493 | + | ||
| 494 | +int SrsGoHttpResponseWriter::write(char* data, int size) | ||
| 495 | +{ | ||
| 496 | + int ret = ERROR_SUCCESS; | ||
| 497 | + | ||
| 498 | + if (!header_wrote) { | ||
| 499 | + write_header(SRS_CONSTS_HTTP_OK); | ||
| 500 | + } | ||
| 501 | + | ||
| 502 | + written += size; | ||
| 503 | + if (content_length != -1 && written > content_length) { | ||
| 504 | + ret = ERROR_HTTP_CONTENT_LENGTH; | ||
| 505 | + srs_error("http: exceed content length. ret=%d", ret); | ||
| 506 | + return ret; | ||
| 507 | + } | ||
| 508 | + | ||
| 509 | + if ((ret = send_header(data, size)) != ERROR_SUCCESS) { | ||
| 510 | + srs_error("http: send header failed. ret=%d", ret); | ||
| 511 | + return ret; | ||
| 512 | + } | ||
| 513 | + | ||
| 514 | + return skt->write((void*)data, size, NULL); | ||
| 515 | +} | ||
| 516 | + | ||
| 517 | +void SrsGoHttpResponseWriter::write_header(int code) | ||
| 518 | +{ | ||
| 519 | + if (header_wrote) { | ||
| 520 | + srs_warn("http: multiple write_header calls, code=%d", code); | ||
| 521 | + return; | ||
| 522 | + } | ||
| 523 | + | ||
| 524 | + header_wrote = true; | ||
| 525 | + status = code; | ||
| 526 | + | ||
| 527 | + // parse the content length from header. | ||
| 528 | + content_length = hdr->content_length(); | ||
| 529 | +} | ||
| 530 | + | ||
| 531 | +int SrsGoHttpResponseWriter::send_header(char* data, int size) | ||
| 532 | +{ | ||
| 533 | + int ret = ERROR_SUCCESS; | ||
| 534 | + | ||
| 535 | + if (header_sent) { | ||
| 536 | + return ret; | ||
| 537 | + } | ||
| 538 | + header_sent = true; | ||
| 539 | + | ||
| 540 | + std::stringstream ss; | ||
| 541 | + | ||
| 542 | + // status_line | ||
| 543 | + ss << "HTTP/1.1 " << status << " " | ||
| 544 | + << srs_generate_status_text(status) << __SRS_CRLF; | ||
| 545 | + | ||
| 546 | + // detect content type | ||
| 547 | + if (srs_go_http_body_allowd(status)) { | ||
| 548 | + if (hdr->content_type().empty()) { | ||
| 549 | + hdr->set_content_type(srs_go_http_detect(data, size)); | ||
| 550 | + } | ||
| 551 | + } | ||
| 552 | + | ||
| 553 | + // set server if not set. | ||
| 554 | + if (hdr->get("Server").empty()) { | ||
| 555 | + hdr->set("Server", RTMP_SIG_SRS_KEY"/"RTMP_SIG_SRS_VERSION); | ||
| 556 | + } | ||
| 557 | + | ||
| 558 | + // write headers | ||
| 559 | + hdr->write(ss); | ||
| 560 | + | ||
| 561 | + // header_eof | ||
| 562 | + ss << __SRS_CRLF; | ||
| 563 | + | ||
| 564 | + std::string buf = ss.str(); | ||
| 565 | + return skt->write((void*)buf.c_str(), buf.length(), NULL); | ||
| 566 | +} | ||
| 567 | + | ||
| 71 | SrsHttpHandlerMatch::SrsHttpHandlerMatch() | 568 | SrsHttpHandlerMatch::SrsHttpHandlerMatch() |
| 72 | { | 569 | { |
| 73 | handler = NULL; | 570 | handler = NULL; |
| @@ -521,13 +1018,6 @@ int SrsHttpHandler::res_error(SrsStSocket* skt, SrsHttpMessage* req, int code, s | @@ -521,13 +1018,6 @@ int SrsHttpHandler::res_error(SrsStSocket* skt, SrsHttpMessage* req, int code, s | ||
| 521 | return res_flush(skt, ss); | 1018 | return res_flush(skt, ss); |
| 522 | } | 1019 | } |
| 523 | 1020 | ||
| 524 | -#ifdef SRS_AUTO_HTTP_API | ||
| 525 | -SrsHttpHandler* SrsHttpHandler::create_http_api() | ||
| 526 | -{ | ||
| 527 | - return new SrsApiRoot(); | ||
| 528 | -} | ||
| 529 | -#endif | ||
| 530 | - | ||
| 531 | #ifdef SRS_AUTO_HTTP_SERVER | 1021 | #ifdef SRS_AUTO_HTTP_SERVER |
| 532 | SrsHttpHandler* SrsHttpHandler::create_http_stream() | 1022 | SrsHttpHandler* SrsHttpHandler::create_http_stream() |
| 533 | { | 1023 | { |
| @@ -553,6 +1043,41 @@ SrsHttpMessage::~SrsHttpMessage() | @@ -553,6 +1043,41 @@ SrsHttpMessage::~SrsHttpMessage() | ||
| 553 | srs_freep(_http_ts_send_buffer); | 1043 | srs_freep(_http_ts_send_buffer); |
| 554 | } | 1044 | } |
| 555 | 1045 | ||
| 1046 | +int SrsHttpMessage::initialize() | ||
| 1047 | +{ | ||
| 1048 | + int ret = ERROR_SUCCESS; | ||
| 1049 | + | ||
| 1050 | + // parse uri to schema/server:port/path?query | ||
| 1051 | + if ((ret = _uri->initialize(_url)) != ERROR_SUCCESS) { | ||
| 1052 | + return ret; | ||
| 1053 | + } | ||
| 1054 | + | ||
| 1055 | + // must format as key=value&...&keyN=valueN | ||
| 1056 | + std::string q = _uri->get_query(); | ||
| 1057 | + size_t pos = string::npos; | ||
| 1058 | + while (!q.empty()) { | ||
| 1059 | + std::string k = q; | ||
| 1060 | + if ((pos = q.find("=")) != string::npos) { | ||
| 1061 | + k = q.substr(0, pos); | ||
| 1062 | + q = q.substr(pos + 1); | ||
| 1063 | + } else { | ||
| 1064 | + q = ""; | ||
| 1065 | + } | ||
| 1066 | + | ||
| 1067 | + std::string v = q; | ||
| 1068 | + if ((pos = q.find("&")) != string::npos) { | ||
| 1069 | + v = q.substr(0, pos); | ||
| 1070 | + q = q.substr(pos + 1); | ||
| 1071 | + } else { | ||
| 1072 | + q = ""; | ||
| 1073 | + } | ||
| 1074 | + | ||
| 1075 | + _query[k] = v; | ||
| 1076 | + } | ||
| 1077 | + | ||
| 1078 | + return ret; | ||
| 1079 | +} | ||
| 1080 | + | ||
| 556 | char* SrsHttpMessage::http_ts_send_buffer() | 1081 | char* SrsHttpMessage::http_ts_send_buffer() |
| 557 | { | 1082 | { |
| 558 | return _http_ts_send_buffer; | 1083 | return _http_ts_send_buffer; |
| @@ -565,24 +1090,6 @@ void SrsHttpMessage::reset() | @@ -565,24 +1090,6 @@ void SrsHttpMessage::reset() | ||
| 565 | _url = ""; | 1090 | _url = ""; |
| 566 | } | 1091 | } |
| 567 | 1092 | ||
| 568 | -int SrsHttpMessage::parse_uri() | ||
| 569 | -{ | ||
| 570 | - // filter url according to HTTP specification. | ||
| 571 | - | ||
| 572 | - // remove the duplicated slash. | ||
| 573 | - std::string filtered_url = srs_string_replace(_url, "//", "/"); | ||
| 574 | - | ||
| 575 | - // remove the last / to match resource. | ||
| 576 | - filtered_url = srs_string_trim_end(filtered_url, "/"); | ||
| 577 | - | ||
| 578 | - // if empty, use root. | ||
| 579 | - if (filtered_url.empty()) { | ||
| 580 | - filtered_url = "/"; | ||
| 581 | - } | ||
| 582 | - | ||
| 583 | - return _uri->initialize(filtered_url); | ||
| 584 | -} | ||
| 585 | - | ||
| 586 | bool SrsHttpMessage::is_complete() | 1093 | bool SrsHttpMessage::is_complete() |
| 587 | { | 1094 | { |
| 588 | return _state == SrsHttpParseStateComplete; | 1095 | return _state == SrsHttpParseStateComplete; |
| @@ -671,11 +1178,6 @@ string SrsHttpMessage::path() | @@ -671,11 +1178,6 @@ string SrsHttpMessage::path() | ||
| 671 | return _uri->get_path(); | 1178 | return _uri->get_path(); |
| 672 | } | 1179 | } |
| 673 | 1180 | ||
| 674 | -string SrsHttpMessage::query() | ||
| 675 | -{ | ||
| 676 | - return _uri->get_query(); | ||
| 677 | -} | ||
| 678 | - | ||
| 679 | string SrsHttpMessage::body() | 1181 | string SrsHttpMessage::body() |
| 680 | { | 1182 | { |
| 681 | std::string b; | 1183 | std::string b; |
| @@ -745,21 +1247,10 @@ void SrsHttpMessage::append_body(const char* body, int length) | @@ -745,21 +1247,10 @@ void SrsHttpMessage::append_body(const char* body, int length) | ||
| 745 | 1247 | ||
| 746 | string SrsHttpMessage::query_get(string key) | 1248 | string SrsHttpMessage::query_get(string key) |
| 747 | { | 1249 | { |
| 748 | - std::string q = query(); | ||
| 749 | - size_t pos = std::string::npos; | 1250 | + std::string v; |
| 750 | 1251 | ||
| 751 | - // must format as key=value&...&keyN=valueN | ||
| 752 | - if ((pos = key.find("=")) != key.length() - 1) { | ||
| 753 | - key = key + "="; | ||
| 754 | - } | ||
| 755 | - | ||
| 756 | - if ((pos = q.find(key)) == std::string::npos) { | ||
| 757 | - return ""; | ||
| 758 | - } | ||
| 759 | - | ||
| 760 | - std::string v = q.substr(pos + key.length()); | ||
| 761 | - if ((pos = v.find("&")) != std::string::npos) { | ||
| 762 | - v = v.substr(0, pos); | 1252 | + if (_query.find(key) != _query.end()) { |
| 1253 | + v = _query[key]; | ||
| 763 | } | 1254 | } |
| 764 | 1255 | ||
| 765 | return v; | 1256 | return v; |
| @@ -860,6 +1351,13 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg) | @@ -860,6 +1351,13 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg) | ||
| 860 | return ret; | 1351 | return ret; |
| 861 | } | 1352 | } |
| 862 | 1353 | ||
| 1354 | + // initalize http msg, parse url. | ||
| 1355 | + if ((ret = msg->initialize()) != ERROR_SUCCESS) { | ||
| 1356 | + srs_error("initialize http msg failed. ret=%d", ret); | ||
| 1357 | + srs_freep(msg); | ||
| 1358 | + return ret; | ||
| 1359 | + } | ||
| 1360 | + | ||
| 863 | // parse ok, return the msg. | 1361 | // parse ok, return the msg. |
| 864 | *ppmsg = msg; | 1362 | *ppmsg = msg; |
| 865 | msg = NULL; | 1363 | msg = NULL; |
| @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | 31 | ||
| 32 | #ifdef SRS_AUTO_HTTP_PARSER | 32 | #ifdef SRS_AUTO_HTTP_PARSER |
| 33 | 33 | ||
| 34 | +#include <map> | ||
| 34 | #include <string> | 35 | #include <string> |
| 35 | #include <vector> | 36 | #include <vector> |
| 36 | #include <sstream> | 37 | #include <sstream> |
| @@ -45,6 +46,7 @@ class SrsStSocket; | @@ -45,6 +46,7 @@ class SrsStSocket; | ||
| 45 | class SrsHttpUri; | 46 | class SrsHttpUri; |
| 46 | class SrsHttpMessage; | 47 | class SrsHttpMessage; |
| 47 | class SrsHttpHandler; | 48 | class SrsHttpHandler; |
| 49 | +class ISrsGoHttpResponseWriter; | ||
| 48 | 50 | ||
| 49 | // http specification | 51 | // http specification |
| 50 | // CR = <US-ASCII CR, carriage return (13)> | 52 | // CR = <US-ASCII CR, carriage return (13)> |
| @@ -65,6 +67,9 @@ class SrsHttpHandler; | @@ -65,6 +67,9 @@ class SrsHttpHandler; | ||
| 65 | // @see SrsHttpMessage._http_ts_send_buffer | 67 | // @see SrsHttpMessage._http_ts_send_buffer |
| 66 | #define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096 | 68 | #define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096 |
| 67 | 69 | ||
| 70 | +// helper function: response in json format. | ||
| 71 | +extern int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, std::string data); | ||
| 72 | + | ||
| 68 | // compare the path. | 73 | // compare the path. |
| 69 | // full compare, extractly match. | 74 | // full compare, extractly match. |
| 70 | // used for api match. | 75 | // used for api match. |
| @@ -81,6 +86,214 @@ enum SrsHttpParseState { | @@ -81,6 +86,214 @@ enum SrsHttpParseState { | ||
| 81 | SrsHttpParseStateComplete | 86 | SrsHttpParseStateComplete |
| 82 | }; | 87 | }; |
| 83 | 88 | ||
| 89 | +// A Header represents the key-value pairs in an HTTP header. | ||
| 90 | +class SrsGoHttpHeader | ||
| 91 | +{ | ||
| 92 | +private: | ||
| 93 | + std::map<std::string, std::string> headers; | ||
| 94 | +public: | ||
| 95 | + SrsGoHttpHeader(); | ||
| 96 | + virtual ~SrsGoHttpHeader(); | ||
| 97 | +public: | ||
| 98 | + // Add adds the key, value pair to the header. | ||
| 99 | + // It appends to any existing values associated with key. | ||
| 100 | + virtual void set(std::string key, std::string value); | ||
| 101 | + // Get gets the first value associated with the given key. | ||
| 102 | + // If there are no values associated with the key, Get returns "". | ||
| 103 | + // To access multiple values of a key, access the map directly | ||
| 104 | + // with CanonicalHeaderKey. | ||
| 105 | + virtual std::string get(std::string key); | ||
| 106 | +public: | ||
| 107 | + /** | ||
| 108 | + * get the content length. -1 if not set. | ||
| 109 | + */ | ||
| 110 | + virtual int64_t content_length(); | ||
| 111 | + /** | ||
| 112 | + * set the content length by header "Content-Length" | ||
| 113 | + */ | ||
| 114 | + virtual void set_content_length(int64_t size); | ||
| 115 | +public: | ||
| 116 | + /** | ||
| 117 | + * get the content type. empty string if not set. | ||
| 118 | + */ | ||
| 119 | + virtual std::string content_type(); | ||
| 120 | + /** | ||
| 121 | + * set the content type by header "Content-Type" | ||
| 122 | + */ | ||
| 123 | + virtual void set_content_type(std::string ct); | ||
| 124 | +public: | ||
| 125 | + /** | ||
| 126 | + * write all headers to string stream. | ||
| 127 | + */ | ||
| 128 | + virtual void write(std::stringstream& ss); | ||
| 129 | +}; | ||
| 130 | + | ||
| 131 | +// A ResponseWriter interface is used by an HTTP handler to | ||
| 132 | +// construct an HTTP response. | ||
| 133 | +class ISrsGoHttpResponseWriter | ||
| 134 | +{ | ||
| 135 | +public: | ||
| 136 | + ISrsGoHttpResponseWriter(); | ||
| 137 | + virtual ~ISrsGoHttpResponseWriter(); | ||
| 138 | +public: | ||
| 139 | + // Header returns the header map that will be sent by WriteHeader. | ||
| 140 | + // Changing the header after a call to WriteHeader (or Write) has | ||
| 141 | + // no effect. | ||
| 142 | + virtual SrsGoHttpHeader* header() = 0; | ||
| 143 | + | ||
| 144 | + // Write writes the data to the connection as part of an HTTP reply. | ||
| 145 | + // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK) | ||
| 146 | + // before writing the data. If the Header does not contain a | ||
| 147 | + // Content-Type line, Write adds a Content-Type set to the result of passing | ||
| 148 | + // the initial 512 bytes of written data to DetectContentType. | ||
| 149 | + virtual int write(char* data, int size) = 0; | ||
| 150 | + | ||
| 151 | + // WriteHeader sends an HTTP response header with status code. | ||
| 152 | + // If WriteHeader is not called explicitly, the first call to Write | ||
| 153 | + // will trigger an implicit WriteHeader(http.StatusOK). | ||
| 154 | + // Thus explicit calls to WriteHeader are mainly used to | ||
| 155 | + // send error codes. | ||
| 156 | + virtual void write_header(int code) = 0; | ||
| 157 | +}; | ||
| 158 | + | ||
| 159 | +// Objects implementing the Handler interface can be | ||
| 160 | +// registered to serve a particular path or subtree | ||
| 161 | +// in the HTTP server. | ||
| 162 | +// | ||
| 163 | +// ServeHTTP should write reply headers and data to the ResponseWriter | ||
| 164 | +// and then return. Returning signals that the request is finished | ||
| 165 | +// and that the HTTP server can move on to the next request on | ||
| 166 | +// the connection. | ||
| 167 | +class ISrsGoHttpHandler | ||
| 168 | +{ | ||
| 169 | +public: | ||
| 170 | + ISrsGoHttpHandler(); | ||
| 171 | + virtual ~ISrsGoHttpHandler(); | ||
| 172 | +public: | ||
| 173 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) = 0; | ||
| 174 | +}; | ||
| 175 | + | ||
| 176 | +// Redirect to a fixed URL | ||
| 177 | +class SrsGoHttpRedirectHandler : public ISrsGoHttpHandler | ||
| 178 | +{ | ||
| 179 | +private: | ||
| 180 | + std::string url; | ||
| 181 | + int code; | ||
| 182 | +public: | ||
| 183 | + SrsGoHttpRedirectHandler(std::string u, int c); | ||
| 184 | + virtual ~SrsGoHttpRedirectHandler(); | ||
| 185 | +public: | ||
| 186 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 187 | +}; | ||
| 188 | + | ||
| 189 | +// NotFound replies to the request with an HTTP 404 not found error. | ||
| 190 | +class SrsGoHttpNotFoundHandler : public ISrsGoHttpHandler | ||
| 191 | +{ | ||
| 192 | +public: | ||
| 193 | + SrsGoHttpNotFoundHandler(); | ||
| 194 | + virtual ~SrsGoHttpNotFoundHandler(); | ||
| 195 | +public: | ||
| 196 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 197 | +}; | ||
| 198 | + | ||
| 199 | +// the mux entry for server mux. | ||
| 200 | +class SrsGoHttpMuxEntry | ||
| 201 | +{ | ||
| 202 | +public: | ||
| 203 | + bool explicit_match; | ||
| 204 | + ISrsGoHttpHandler* handler; | ||
| 205 | + std::string pattern; | ||
| 206 | +public: | ||
| 207 | + SrsGoHttpMuxEntry(); | ||
| 208 | + virtual ~SrsGoHttpMuxEntry(); | ||
| 209 | +}; | ||
| 210 | + | ||
| 211 | +// ServeMux is an HTTP request multiplexer. | ||
| 212 | +// It matches the URL of each incoming request against a list of registered | ||
| 213 | +// patterns and calls the handler for the pattern that | ||
| 214 | +// most closely matches the URL. | ||
| 215 | +// | ||
| 216 | +// Patterns name fixed, rooted paths, like "/favicon.ico", | ||
| 217 | +// or rooted subtrees, like "/images/" (note the trailing slash). | ||
| 218 | +// Longer patterns take precedence over shorter ones, so that | ||
| 219 | +// if there are handlers registered for both "/images/" | ||
| 220 | +// and "/images/thumbnails/", the latter handler will be | ||
| 221 | +// called for paths beginning "/images/thumbnails/" and the | ||
| 222 | +// former will receive requests for any other paths in the | ||
| 223 | +// "/images/" subtree. | ||
| 224 | +// | ||
| 225 | +// Note that since a pattern ending in a slash names a rooted subtree, | ||
| 226 | +// the pattern "/" matches all paths not matched by other registered | ||
| 227 | +// patterns, not just the URL with Path == "/". | ||
| 228 | +// | ||
| 229 | +// Patterns may optionally begin with a host name, restricting matches to | ||
| 230 | +// URLs on that host only. Host-specific patterns take precedence over | ||
| 231 | +// general patterns, so that a handler might register for the two patterns | ||
| 232 | +// "/codesearch" and "codesearch.google.com/" without also taking over | ||
| 233 | +// requests for "http://www.google.com/". | ||
| 234 | +// | ||
| 235 | +// ServeMux also takes care of sanitizing the URL request path, | ||
| 236 | +// redirecting any request containing . or .. elements to an | ||
| 237 | +// equivalent .- and ..-free URL. | ||
| 238 | +class SrsGoHttpServeMux | ||
| 239 | +{ | ||
| 240 | +private: | ||
| 241 | + std::map<std::string, SrsGoHttpMuxEntry*> entries; | ||
| 242 | +public: | ||
| 243 | + SrsGoHttpServeMux(); | ||
| 244 | + virtual ~SrsGoHttpServeMux(); | ||
| 245 | +public: | ||
| 246 | + /** | ||
| 247 | + * initialize the http serve mux. | ||
| 248 | + */ | ||
| 249 | + virtual int initialize(); | ||
| 250 | +public: | ||
| 251 | + // Handle registers the handler for the given pattern. | ||
| 252 | + // If a handler already exists for pattern, Handle panics. | ||
| 253 | + virtual int handle(std::string pattern, ISrsGoHttpHandler* handler); | ||
| 254 | +// interface ISrsGoHttpHandler | ||
| 255 | +public: | ||
| 256 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); | ||
| 257 | +private: | ||
| 258 | + virtual int find_handler(SrsHttpMessage* r, ISrsGoHttpHandler** ph); | ||
| 259 | + virtual int match(SrsHttpMessage* r, ISrsGoHttpHandler** ph); | ||
| 260 | + virtual bool path_match(std::string pattern, std::string path); | ||
| 261 | +}; | ||
| 262 | + | ||
| 263 | +/** | ||
| 264 | +* response writer use st socket | ||
| 265 | +*/ | ||
| 266 | +class SrsGoHttpResponseWriter : public ISrsGoHttpResponseWriter | ||
| 267 | +{ | ||
| 268 | +private: | ||
| 269 | + SrsStSocket* skt; | ||
| 270 | + SrsGoHttpHeader* hdr; | ||
| 271 | +private: | ||
| 272 | + // reply header has been (logically) written | ||
| 273 | + bool header_wrote; | ||
| 274 | + // status code passed to WriteHeader | ||
| 275 | + int status; | ||
| 276 | +private: | ||
| 277 | + // explicitly-declared Content-Length; or -1 | ||
| 278 | + int64_t content_length; | ||
| 279 | + // number of bytes written in body | ||
| 280 | + int64_t written; | ||
| 281 | +private: | ||
| 282 | + // wroteHeader tells whether the header's been written to "the | ||
| 283 | + // wire" (or rather: w.conn.buf). this is unlike | ||
| 284 | + // (*response).wroteHeader, which tells only whether it was | ||
| 285 | + // logically written. | ||
| 286 | + bool header_sent; | ||
| 287 | +public: | ||
| 288 | + SrsGoHttpResponseWriter(SrsStSocket* io); | ||
| 289 | + virtual ~SrsGoHttpResponseWriter(); | ||
| 290 | +public: | ||
| 291 | + virtual SrsGoHttpHeader* header(); | ||
| 292 | + virtual int write(char* data, int size); | ||
| 293 | + virtual void write_header(int code); | ||
| 294 | + virtual int send_header(char* data, int size); | ||
| 295 | +}; | ||
| 296 | + | ||
| 84 | /** | 297 | /** |
| 85 | * the matched handler info. | 298 | * the matched handler info. |
| 86 | */ | 299 | */ |
| @@ -183,12 +396,6 @@ public: | @@ -183,12 +396,6 @@ public: | ||
| 183 | // object creator | 396 | // object creator |
| 184 | public: | 397 | public: |
| 185 | /** | 398 | /** |
| 186 | - * create http api resource handler. | ||
| 187 | - */ | ||
| 188 | -#ifdef SRS_AUTO_HTTP_API | ||
| 189 | - static SrsHttpHandler* create_http_api(); | ||
| 190 | -#endif | ||
| 191 | - /** | ||
| 192 | * create http stream resource handler. | 399 | * create http stream resource handler. |
| 193 | */ | 400 | */ |
| 194 | #ifdef SRS_AUTO_HTTP_SERVER | 401 | #ifdef SRS_AUTO_HTTP_SERVER |
| @@ -196,6 +403,12 @@ public: | @@ -196,6 +403,12 @@ public: | ||
| 196 | #endif | 403 | #endif |
| 197 | }; | 404 | }; |
| 198 | 405 | ||
| 406 | +// A Request represents an HTTP request received by a server | ||
| 407 | +// or to be sent by a client. | ||
| 408 | +// | ||
| 409 | +// The field semantics differ slightly between client and server | ||
| 410 | +// usage. In addition to the notes on the fields below, see the | ||
| 411 | +// documentation for Request.Write and RoundTripper. | ||
| 199 | /** | 412 | /** |
| 200 | * the http message, request or response. | 413 | * the http message, request or response. |
| 201 | */ | 414 | */ |
| @@ -239,13 +452,16 @@ private: | @@ -239,13 +452,16 @@ private: | ||
| 239 | // http headers | 452 | // http headers |
| 240 | typedef std::pair<std::string, std::string> SrsHttpHeaderField; | 453 | typedef std::pair<std::string, std::string> SrsHttpHeaderField; |
| 241 | std::vector<SrsHttpHeaderField> headers; | 454 | std::vector<SrsHttpHeaderField> headers; |
| 455 | + // the query map | ||
| 456 | + std::map<std::string, std::string> _query; | ||
| 242 | public: | 457 | public: |
| 243 | SrsHttpMessage(); | 458 | SrsHttpMessage(); |
| 244 | virtual ~SrsHttpMessage(); | 459 | virtual ~SrsHttpMessage(); |
| 245 | public: | 460 | public: |
| 461 | + virtual int initialize(); | ||
| 462 | +public: | ||
| 246 | virtual char* http_ts_send_buffer(); | 463 | virtual char* http_ts_send_buffer(); |
| 247 | virtual void reset(); | 464 | virtual void reset(); |
| 248 | - virtual int parse_uri(); | ||
| 249 | public: | 465 | public: |
| 250 | virtual bool is_complete(); | 466 | virtual bool is_complete(); |
| 251 | virtual u_int8_t method(); | 467 | virtual u_int8_t method(); |
| @@ -260,7 +476,7 @@ public: | @@ -260,7 +476,7 @@ public: | ||
| 260 | virtual std::string url(); | 476 | virtual std::string url(); |
| 261 | virtual std::string host(); | 477 | virtual std::string host(); |
| 262 | virtual std::string path(); | 478 | virtual std::string path(); |
| 263 | - virtual std::string query(); | 479 | +public: |
| 264 | virtual std::string body(); | 480 | virtual std::string body(); |
| 265 | virtual char* body_raw(); | 481 | virtual char* body_raw(); |
| 266 | virtual int64_t body_size(); | 482 | virtual int64_t body_size(); |
| @@ -273,14 +489,12 @@ public: | @@ -273,14 +489,12 @@ public: | ||
| 273 | virtual void set_match(SrsHttpHandlerMatch* match); | 489 | virtual void set_match(SrsHttpHandlerMatch* match); |
| 274 | virtual void set_requires_crossdomain(bool requires_crossdomain); | 490 | virtual void set_requires_crossdomain(bool requires_crossdomain); |
| 275 | virtual void append_body(const char* body, int length); | 491 | virtual void append_body(const char* body, int length); |
| 276 | -public: | ||
| 277 | /** | 492 | /** |
| 278 | * get the param in query string, | 493 | * get the param in query string, |
| 279 | * for instance, query is "start=100&end=200", | 494 | * for instance, query is "start=100&end=200", |
| 280 | * then query_get("start") is "100", and query_get("end") is "200" | 495 | * then query_get("start") is "100", and query_get("end") is "200" |
| 281 | */ | 496 | */ |
| 282 | virtual std::string query_get(std::string key); | 497 | virtual std::string query_get(std::string key); |
| 283 | -public: | ||
| 284 | virtual int request_header_count(); | 498 | virtual int request_header_count(); |
| 285 | virtual std::string request_header_key_at(int index); | 499 | virtual std::string request_header_key_at(int index); |
| 286 | virtual std::string request_header_value_at(int index); | 500 | virtual std::string request_header_value_at(int index); |
| @@ -38,41 +38,15 @@ using namespace std; | @@ -38,41 +38,15 @@ using namespace std; | ||
| 38 | #include <srs_app_statistic.hpp> | 38 | #include <srs_app_statistic.hpp> |
| 39 | #include <srs_protocol_rtmp.hpp> | 39 | #include <srs_protocol_rtmp.hpp> |
| 40 | 40 | ||
| 41 | -SrsApiRoot::SrsApiRoot() | 41 | +SrsGoApiRoot::SrsGoApiRoot() |
| 42 | { | 42 | { |
| 43 | - handlers.push_back(new SrsApiApi()); | ||
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | -SrsApiRoot::~SrsApiRoot() | 45 | +SrsGoApiRoot::~SrsGoApiRoot() |
| 47 | { | 46 | { |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | -bool SrsApiRoot::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase) | ||
| 51 | -{ | ||
| 52 | - if (!SrsHttpHandler::is_handler_valid(req, status_code, reason_phrase)) { | ||
| 53 | - return false; | ||
| 54 | - } | ||
| 55 | - | ||
| 56 | - if (req->match()->matched_url.length() != 1) { | ||
| 57 | - status_code = SRS_CONSTS_HTTP_NotFound; | ||
| 58 | - reason_phrase = SRS_CONSTS_HTTP_NotFound_str; | ||
| 59 | - return false; | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - return true; | ||
| 63 | -} | ||
| 64 | - | ||
| 65 | -bool SrsApiRoot::can_handle(const char* path, int /*length*/, const char** pchild) | ||
| 66 | -{ | ||
| 67 | - // reset the child path to path, | ||
| 68 | - // for child to reparse the path. | ||
| 69 | - *pchild = path; | ||
| 70 | - | ||
| 71 | - // only compare the first char. | ||
| 72 | - return srs_path_equals("/", path, 1); | ||
| 73 | -} | ||
| 74 | - | ||
| 75 | -int SrsApiRoot::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 49 | +int SrsGoApiRoot::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 76 | { | 50 | { |
| 77 | std::stringstream ss; | 51 | std::stringstream ss; |
| 78 | 52 | ||
| @@ -83,24 +57,18 @@ int SrsApiRoot::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -83,24 +57,18 @@ int SrsApiRoot::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 83 | << __SRS_JOBJECT_END | 57 | << __SRS_JOBJECT_END |
| 84 | << __SRS_JOBJECT_END; | 58 | << __SRS_JOBJECT_END; |
| 85 | 59 | ||
| 86 | - return res_json(skt, req, ss.str()); | 60 | + return srs_go_http_response_json(w, ss.str()); |
| 87 | } | 61 | } |
| 88 | 62 | ||
| 89 | -SrsApiApi::SrsApiApi() | 63 | +SrsGoApiApi::SrsGoApiApi() |
| 90 | { | 64 | { |
| 91 | - handlers.push_back(new SrsApiV1()); | ||
| 92 | } | 65 | } |
| 93 | 66 | ||
| 94 | -SrsApiApi::~SrsApiApi() | 67 | +SrsGoApiApi::~SrsGoApiApi() |
| 95 | { | 68 | { |
| 96 | } | 69 | } |
| 97 | 70 | ||
| 98 | -bool SrsApiApi::can_handle(const char* path, int length, const char** /*pchild*/) | ||
| 99 | -{ | ||
| 100 | - return srs_path_equals("/api", path, length); | ||
| 101 | -} | ||
| 102 | - | ||
| 103 | -int SrsApiApi::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 71 | +int SrsGoApiApi::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 104 | { | 72 | { |
| 105 | std::stringstream ss; | 73 | std::stringstream ss; |
| 106 | 74 | ||
| @@ -111,33 +79,18 @@ int SrsApiApi::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -111,33 +79,18 @@ int SrsApiApi::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 111 | << __SRS_JOBJECT_END | 79 | << __SRS_JOBJECT_END |
| 112 | << __SRS_JOBJECT_END; | 80 | << __SRS_JOBJECT_END; |
| 113 | 81 | ||
| 114 | - return res_json(skt, req, ss.str()); | ||
| 115 | -} | ||
| 116 | - | ||
| 117 | -SrsApiV1::SrsApiV1() | ||
| 118 | -{ | ||
| 119 | - handlers.push_back(new SrsApiVersion()); | ||
| 120 | - handlers.push_back(new SrsApiSummaries()); | ||
| 121 | - handlers.push_back(new SrsApiRusages()); | ||
| 122 | - handlers.push_back(new SrsApiSelfProcStats()); | ||
| 123 | - handlers.push_back(new SrsApiSystemProcStats()); | ||
| 124 | - handlers.push_back(new SrsApiMemInfos()); | ||
| 125 | - handlers.push_back(new SrsApiAuthors()); | ||
| 126 | - handlers.push_back(new SrsApiRequests()); | ||
| 127 | - handlers.push_back(new SrsApiVhosts()); | ||
| 128 | - handlers.push_back(new SrsApiStreams()); | 82 | + return srs_go_http_response_json(w, ss.str()); |
| 129 | } | 83 | } |
| 130 | 84 | ||
| 131 | -SrsApiV1::~SrsApiV1() | 85 | +SrsGoApiV1::SrsGoApiV1() |
| 132 | { | 86 | { |
| 133 | } | 87 | } |
| 134 | 88 | ||
| 135 | -bool SrsApiV1::can_handle(const char* path, int length, const char** /*pchild*/) | 89 | +SrsGoApiV1::~SrsGoApiV1() |
| 136 | { | 90 | { |
| 137 | - return srs_path_equals("/v1", path, length); | ||
| 138 | } | 91 | } |
| 139 | 92 | ||
| 140 | -int SrsApiV1::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 93 | +int SrsGoApiV1::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 141 | { | 94 | { |
| 142 | std::stringstream ss; | 95 | std::stringstream ss; |
| 143 | 96 | ||
| @@ -157,87 +110,18 @@ int SrsApiV1::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -157,87 +110,18 @@ int SrsApiV1::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 157 | << __SRS_JOBJECT_END | 110 | << __SRS_JOBJECT_END |
| 158 | << __SRS_JOBJECT_END; | 111 | << __SRS_JOBJECT_END; |
| 159 | 112 | ||
| 160 | - return res_json(skt, req, ss.str()); | ||
| 161 | -} | ||
| 162 | - | ||
| 163 | -SrsApiRequests::SrsApiRequests() | ||
| 164 | -{ | ||
| 165 | -} | ||
| 166 | - | ||
| 167 | -SrsApiRequests::~SrsApiRequests() | ||
| 168 | -{ | ||
| 169 | -} | ||
| 170 | - | ||
| 171 | -bool SrsApiRequests::can_handle(const char* path, int length, const char** /*pchild*/) | ||
| 172 | -{ | ||
| 173 | - return srs_path_equals("/requests", path, length); | ||
| 174 | -} | ||
| 175 | - | ||
| 176 | -int SrsApiRequests::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 177 | -{ | ||
| 178 | - std::stringstream ss; | ||
| 179 | - | ||
| 180 | - ss << __SRS_JOBJECT_START | ||
| 181 | - << __SRS_JFIELD_ERROR(ERROR_SUCCESS) << __SRS_JFIELD_CONT | ||
| 182 | - << __SRS_JFIELD_ORG("data", __SRS_JOBJECT_START) | ||
| 183 | - << __SRS_JFIELD_STR("uri", req->uri()) << __SRS_JFIELD_CONT | ||
| 184 | - << __SRS_JFIELD_STR("path", req->path()) << __SRS_JFIELD_CONT; | ||
| 185 | - | ||
| 186 | - // method | ||
| 187 | - if (req->is_http_get()) { | ||
| 188 | - ss << __SRS_JFIELD_STR("METHOD", "GET"); | ||
| 189 | - } else if (req->is_http_post()) { | ||
| 190 | - ss << __SRS_JFIELD_STR("METHOD", "POST"); | ||
| 191 | - } else if (req->is_http_put()) { | ||
| 192 | - ss << __SRS_JFIELD_STR("METHOD", "PUT"); | ||
| 193 | - } else if (req->is_http_delete()) { | ||
| 194 | - ss << __SRS_JFIELD_STR("METHOD", "DELETE"); | ||
| 195 | - } else { | ||
| 196 | - ss << __SRS_JFIELD_ORG("METHOD", req->method()); | ||
| 197 | - } | ||
| 198 | - ss << __SRS_JFIELD_CONT; | ||
| 199 | - | ||
| 200 | - // request headers | ||
| 201 | - ss << __SRS_JFIELD_NAME("headers") << __SRS_JOBJECT_START; | ||
| 202 | - for (int i = 0; i < req->request_header_count(); i++) { | ||
| 203 | - std::string key = req->request_header_key_at(i); | ||
| 204 | - std::string value = req->request_header_value_at(i); | ||
| 205 | - if ( i < req->request_header_count() - 1) { | ||
| 206 | - ss << __SRS_JFIELD_STR(key, value) << __SRS_JFIELD_CONT; | ||
| 207 | - } else { | ||
| 208 | - ss << __SRS_JFIELD_STR(key, value); | ||
| 209 | - } | ||
| 210 | - } | ||
| 211 | - ss << __SRS_JOBJECT_END << __SRS_JFIELD_CONT; | ||
| 212 | - | ||
| 213 | - // server informations | ||
| 214 | - ss << __SRS_JFIELD_NAME("server") << __SRS_JOBJECT_START | ||
| 215 | - << __SRS_JFIELD_STR("sigature", RTMP_SIG_SRS_KEY) << __SRS_JFIELD_CONT | ||
| 216 | - << __SRS_JFIELD_STR("name", RTMP_SIG_SRS_NAME) << __SRS_JFIELD_CONT | ||
| 217 | - << __SRS_JFIELD_STR("version", RTMP_SIG_SRS_VERSION) << __SRS_JFIELD_CONT | ||
| 218 | - << __SRS_JFIELD_STR("link", RTMP_SIG_SRS_URL) << __SRS_JFIELD_CONT | ||
| 219 | - << __SRS_JFIELD_ORG("time", srs_get_system_time_ms()) | ||
| 220 | - << __SRS_JOBJECT_END | ||
| 221 | - << __SRS_JOBJECT_END | ||
| 222 | - << __SRS_JOBJECT_END; | ||
| 223 | - | ||
| 224 | - return res_json(skt, req, ss.str()); | ||
| 225 | -} | ||
| 226 | - | ||
| 227 | -SrsApiVersion::SrsApiVersion() | ||
| 228 | -{ | 113 | + return srs_go_http_response_json(w, ss.str()); |
| 229 | } | 114 | } |
| 230 | 115 | ||
| 231 | -SrsApiVersion::~SrsApiVersion() | 116 | +SrsGoApiVersion::SrsGoApiVersion() |
| 232 | { | 117 | { |
| 233 | } | 118 | } |
| 234 | 119 | ||
| 235 | -bool SrsApiVersion::can_handle(const char* path, int length, const char** /*pchild*/) | 120 | +SrsGoApiVersion::~SrsGoApiVersion() |
| 236 | { | 121 | { |
| 237 | - return srs_path_equals("/versions", path, length); | ||
| 238 | } | 122 | } |
| 239 | 123 | ||
| 240 | -int SrsApiVersion::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 124 | +int SrsGoApiVersion::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 241 | { | 125 | { |
| 242 | std::stringstream ss; | 126 | std::stringstream ss; |
| 243 | 127 | ||
| @@ -251,43 +135,33 @@ int SrsApiVersion::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -251,43 +135,33 @@ int SrsApiVersion::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 251 | << __SRS_JOBJECT_END | 135 | << __SRS_JOBJECT_END |
| 252 | << __SRS_JOBJECT_END; | 136 | << __SRS_JOBJECT_END; |
| 253 | 137 | ||
| 254 | - return res_json(skt, req, ss.str()); | 138 | + return srs_go_http_response_json(w, ss.str()); |
| 255 | } | 139 | } |
| 256 | 140 | ||
| 257 | -SrsApiSummaries::SrsApiSummaries() | 141 | +SrsGoApiSummaries::SrsGoApiSummaries() |
| 258 | { | 142 | { |
| 259 | } | 143 | } |
| 260 | 144 | ||
| 261 | -SrsApiSummaries::~SrsApiSummaries() | 145 | +SrsGoApiSummaries::~SrsGoApiSummaries() |
| 262 | { | 146 | { |
| 263 | } | 147 | } |
| 264 | 148 | ||
| 265 | -bool SrsApiSummaries::can_handle(const char* path, int length, const char** /*pchild*/) | ||
| 266 | -{ | ||
| 267 | - return srs_path_equals("/summaries", path, length); | ||
| 268 | -} | ||
| 269 | - | ||
| 270 | -int SrsApiSummaries::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 149 | +int SrsGoApiSummaries::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 271 | { | 150 | { |
| 272 | std::stringstream ss; | 151 | std::stringstream ss; |
| 273 | srs_api_dump_summaries(ss); | 152 | srs_api_dump_summaries(ss); |
| 274 | - return res_json(skt, req, ss.str()); | 153 | + return srs_go_http_response_json(w, ss.str()); |
| 275 | } | 154 | } |
| 276 | 155 | ||
| 277 | -SrsApiRusages::SrsApiRusages() | 156 | +SrsGoApiRusages::SrsGoApiRusages() |
| 278 | { | 157 | { |
| 279 | } | 158 | } |
| 280 | 159 | ||
| 281 | -SrsApiRusages::~SrsApiRusages() | 160 | +SrsGoApiRusages::~SrsGoApiRusages() |
| 282 | { | 161 | { |
| 283 | } | 162 | } |
| 284 | 163 | ||
| 285 | -bool SrsApiRusages::can_handle(const char* path, int length, const char** /*pchild*/) | ||
| 286 | -{ | ||
| 287 | - return srs_path_equals("/rusages", path, length); | ||
| 288 | -} | ||
| 289 | - | ||
| 290 | -int SrsApiRusages::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 164 | +int SrsGoApiRusages::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* req) |
| 291 | { | 165 | { |
| 292 | std::stringstream ss; | 166 | std::stringstream ss; |
| 293 | 167 | ||
| @@ -317,23 +191,18 @@ int SrsApiRusages::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -317,23 +191,18 @@ int SrsApiRusages::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 317 | << __SRS_JOBJECT_END | 191 | << __SRS_JOBJECT_END |
| 318 | << __SRS_JOBJECT_END; | 192 | << __SRS_JOBJECT_END; |
| 319 | 193 | ||
| 320 | - return res_json(skt, req, ss.str()); | ||
| 321 | -} | ||
| 322 | - | ||
| 323 | -SrsApiSelfProcStats::SrsApiSelfProcStats() | ||
| 324 | -{ | 194 | + return srs_go_http_response_json(w, ss.str()); |
| 325 | } | 195 | } |
| 326 | 196 | ||
| 327 | -SrsApiSelfProcStats::~SrsApiSelfProcStats() | 197 | +SrsGoApiSelfProcStats::SrsGoApiSelfProcStats() |
| 328 | { | 198 | { |
| 329 | } | 199 | } |
| 330 | 200 | ||
| 331 | -bool SrsApiSelfProcStats::can_handle(const char* path, int length, const char** /*pchild*/) | 201 | +SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats() |
| 332 | { | 202 | { |
| 333 | - return srs_path_equals("/self_proc_stats", path, length); | ||
| 334 | } | 203 | } |
| 335 | 204 | ||
| 336 | -int SrsApiSelfProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 205 | +int SrsGoApiSelfProcStats::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 337 | { | 206 | { |
| 338 | std::stringstream ss; | 207 | std::stringstream ss; |
| 339 | 208 | ||
| @@ -392,23 +261,18 @@ int SrsApiSelfProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* re | @@ -392,23 +261,18 @@ int SrsApiSelfProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* re | ||
| 392 | << __SRS_JOBJECT_END | 261 | << __SRS_JOBJECT_END |
| 393 | << __SRS_JOBJECT_END; | 262 | << __SRS_JOBJECT_END; |
| 394 | 263 | ||
| 395 | - return res_json(skt, req, ss.str()); | 264 | + return srs_go_http_response_json(w, ss.str()); |
| 396 | } | 265 | } |
| 397 | 266 | ||
| 398 | -SrsApiSystemProcStats::SrsApiSystemProcStats() | 267 | +SrsGoApiSystemProcStats::SrsGoApiSystemProcStats() |
| 399 | { | 268 | { |
| 400 | } | 269 | } |
| 401 | 270 | ||
| 402 | -SrsApiSystemProcStats::~SrsApiSystemProcStats() | 271 | +SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats() |
| 403 | { | 272 | { |
| 404 | } | 273 | } |
| 405 | 274 | ||
| 406 | -bool SrsApiSystemProcStats::can_handle(const char* path, int length, const char** /*pchild*/) | ||
| 407 | -{ | ||
| 408 | - return srs_path_equals("/system_proc_stats", path, length); | ||
| 409 | -} | ||
| 410 | - | ||
| 411 | -int SrsApiSystemProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 275 | +int SrsGoApiSystemProcStats::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 412 | { | 276 | { |
| 413 | std::stringstream ss; | 277 | std::stringstream ss; |
| 414 | 278 | ||
| @@ -432,23 +296,18 @@ int SrsApiSystemProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* | @@ -432,23 +296,18 @@ int SrsApiSystemProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* | ||
| 432 | << __SRS_JOBJECT_END | 296 | << __SRS_JOBJECT_END |
| 433 | << __SRS_JOBJECT_END; | 297 | << __SRS_JOBJECT_END; |
| 434 | 298 | ||
| 435 | - return res_json(skt, req, ss.str()); | ||
| 436 | -} | ||
| 437 | - | ||
| 438 | -SrsApiMemInfos::SrsApiMemInfos() | ||
| 439 | -{ | 299 | + return srs_go_http_response_json(w, ss.str()); |
| 440 | } | 300 | } |
| 441 | 301 | ||
| 442 | -SrsApiMemInfos::~SrsApiMemInfos() | 302 | +SrsGoApiMemInfos::SrsGoApiMemInfos() |
| 443 | { | 303 | { |
| 444 | } | 304 | } |
| 445 | 305 | ||
| 446 | -bool SrsApiMemInfos::can_handle(const char* path, int length, const char** /*pchild*/) | 306 | +SrsGoApiMemInfos::~SrsGoApiMemInfos() |
| 447 | { | 307 | { |
| 448 | - return srs_path_equals("/meminfos", path, length); | ||
| 449 | } | 308 | } |
| 450 | 309 | ||
| 451 | -int SrsApiMemInfos::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 310 | +int SrsGoApiMemInfos::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 452 | { | 311 | { |
| 453 | std::stringstream ss; | 312 | std::stringstream ss; |
| 454 | 313 | ||
| @@ -473,23 +332,18 @@ int SrsApiMemInfos::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -473,23 +332,18 @@ int SrsApiMemInfos::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 473 | << __SRS_JOBJECT_END | 332 | << __SRS_JOBJECT_END |
| 474 | << __SRS_JOBJECT_END; | 333 | << __SRS_JOBJECT_END; |
| 475 | 334 | ||
| 476 | - return res_json(skt, req, ss.str()); | 335 | + return srs_go_http_response_json(w, ss.str()); |
| 477 | } | 336 | } |
| 478 | 337 | ||
| 479 | -SrsApiAuthors::SrsApiAuthors() | 338 | +SrsGoApiAuthors::SrsGoApiAuthors() |
| 480 | { | 339 | { |
| 481 | } | 340 | } |
| 482 | 341 | ||
| 483 | -SrsApiAuthors::~SrsApiAuthors() | 342 | +SrsGoApiAuthors::~SrsGoApiAuthors() |
| 484 | { | 343 | { |
| 485 | } | 344 | } |
| 486 | 345 | ||
| 487 | -bool SrsApiAuthors::can_handle(const char* path, int length, const char** /*pchild*/) | ||
| 488 | -{ | ||
| 489 | - return srs_path_equals("/authors", path, length); | ||
| 490 | -} | ||
| 491 | - | ||
| 492 | -int SrsApiAuthors::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 346 | +int SrsGoApiAuthors::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 493 | { | 347 | { |
| 494 | std::stringstream ss; | 348 | std::stringstream ss; |
| 495 | 349 | ||
| @@ -503,24 +357,82 @@ int SrsApiAuthors::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -503,24 +357,82 @@ int SrsApiAuthors::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 503 | << __SRS_JOBJECT_END | 357 | << __SRS_JOBJECT_END |
| 504 | << __SRS_JOBJECT_END; | 358 | << __SRS_JOBJECT_END; |
| 505 | 359 | ||
| 506 | - return res_json(skt, req, ss.str()); | 360 | + return srs_go_http_response_json(w, ss.str()); |
| 507 | } | 361 | } |
| 508 | 362 | ||
| 509 | -SrsApiVhosts::SrsApiVhosts() | 363 | +SrsGoApiRequests::SrsGoApiRequests() |
| 510 | { | 364 | { |
| 511 | } | 365 | } |
| 512 | 366 | ||
| 513 | -SrsApiVhosts::~SrsApiVhosts() | 367 | +SrsGoApiRequests::~SrsGoApiRequests() |
| 514 | { | 368 | { |
| 515 | } | 369 | } |
| 516 | 370 | ||
| 517 | -bool SrsApiVhosts::can_handle(const char* path, int length, const char** /*pchild*/) | 371 | +int SrsGoApiRequests::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 518 | { | 372 | { |
| 519 | - return srs_path_equals("/vhosts", path, length); | 373 | + SrsHttpMessage* req = r; |
| 374 | + | ||
| 375 | + std::stringstream ss; | ||
| 376 | + | ||
| 377 | + ss << __SRS_JOBJECT_START | ||
| 378 | + << __SRS_JFIELD_ERROR(ERROR_SUCCESS) << __SRS_JFIELD_CONT | ||
| 379 | + << __SRS_JFIELD_ORG("data", __SRS_JOBJECT_START) | ||
| 380 | + << __SRS_JFIELD_STR("uri", req->uri()) << __SRS_JFIELD_CONT | ||
| 381 | + << __SRS_JFIELD_STR("path", req->path()) << __SRS_JFIELD_CONT; | ||
| 382 | + | ||
| 383 | + // method | ||
| 384 | + if (req->is_http_get()) { | ||
| 385 | + ss << __SRS_JFIELD_STR("METHOD", "GET"); | ||
| 386 | + } else if (req->is_http_post()) { | ||
| 387 | + ss << __SRS_JFIELD_STR("METHOD", "POST"); | ||
| 388 | + } else if (req->is_http_put()) { | ||
| 389 | + ss << __SRS_JFIELD_STR("METHOD", "PUT"); | ||
| 390 | + } else if (req->is_http_delete()) { | ||
| 391 | + ss << __SRS_JFIELD_STR("METHOD", "DELETE"); | ||
| 392 | + } else { | ||
| 393 | + ss << __SRS_JFIELD_ORG("METHOD", req->method()); | ||
| 394 | + } | ||
| 395 | + ss << __SRS_JFIELD_CONT; | ||
| 396 | + | ||
| 397 | + // request headers | ||
| 398 | + ss << __SRS_JFIELD_NAME("headers") << __SRS_JOBJECT_START; | ||
| 399 | + for (int i = 0; i < req->request_header_count(); i++) { | ||
| 400 | + std::string key = req->request_header_key_at(i); | ||
| 401 | + std::string value = req->request_header_value_at(i); | ||
| 402 | + if ( i < req->request_header_count() - 1) { | ||
| 403 | + ss << __SRS_JFIELD_STR(key, value) << __SRS_JFIELD_CONT; | ||
| 404 | + } else { | ||
| 405 | + ss << __SRS_JFIELD_STR(key, value); | ||
| 406 | + } | ||
| 407 | + } | ||
| 408 | + ss << __SRS_JOBJECT_END << __SRS_JFIELD_CONT; | ||
| 409 | + | ||
| 410 | + // server informations | ||
| 411 | + ss << __SRS_JFIELD_NAME("server") << __SRS_JOBJECT_START | ||
| 412 | + << __SRS_JFIELD_STR("sigature", RTMP_SIG_SRS_KEY) << __SRS_JFIELD_CONT | ||
| 413 | + << __SRS_JFIELD_STR("name", RTMP_SIG_SRS_NAME) << __SRS_JFIELD_CONT | ||
| 414 | + << __SRS_JFIELD_STR("version", RTMP_SIG_SRS_VERSION) << __SRS_JFIELD_CONT | ||
| 415 | + << __SRS_JFIELD_STR("link", RTMP_SIG_SRS_URL) << __SRS_JFIELD_CONT | ||
| 416 | + << __SRS_JFIELD_ORG("time", srs_get_system_time_ms()) | ||
| 417 | + << __SRS_JOBJECT_END | ||
| 418 | + << __SRS_JOBJECT_END | ||
| 419 | + << __SRS_JOBJECT_END; | ||
| 420 | + | ||
| 421 | + return srs_go_http_response_json(w, ss.str()); | ||
| 520 | } | 422 | } |
| 521 | 423 | ||
| 522 | -int SrsApiVhosts::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 424 | +SrsGoApiVhosts::SrsGoApiVhosts() |
| 523 | { | 425 | { |
| 426 | +} | ||
| 427 | + | ||
| 428 | +SrsGoApiVhosts::~SrsGoApiVhosts() | ||
| 429 | +{ | ||
| 430 | +} | ||
| 431 | + | ||
| 432 | +int SrsGoApiVhosts::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) | ||
| 433 | +{ | ||
| 434 | + SrsHttpMessage* req = r; | ||
| 435 | + | ||
| 524 | std::stringstream data; | 436 | std::stringstream data; |
| 525 | SrsStatistic* stat = SrsStatistic::instance(); | 437 | SrsStatistic* stat = SrsStatistic::instance(); |
| 526 | int ret = stat->dumps_vhosts(data); | 438 | int ret = stat->dumps_vhosts(data); |
| @@ -533,23 +445,18 @@ int SrsApiVhosts::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -533,23 +445,18 @@ int SrsApiVhosts::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 533 | << __SRS_JFIELD_ORG("vhosts", data.str()) | 445 | << __SRS_JFIELD_ORG("vhosts", data.str()) |
| 534 | << __SRS_JOBJECT_END; | 446 | << __SRS_JOBJECT_END; |
| 535 | 447 | ||
| 536 | - return res_json(skt, req, ss.str()); | ||
| 537 | -} | ||
| 538 | - | ||
| 539 | -SrsApiStreams::SrsApiStreams() | ||
| 540 | -{ | 448 | + return srs_go_http_response_json(w, ss.str()); |
| 541 | } | 449 | } |
| 542 | 450 | ||
| 543 | -SrsApiStreams::~SrsApiStreams() | 451 | +SrsGoApiStreams::SrsGoApiStreams() |
| 544 | { | 452 | { |
| 545 | } | 453 | } |
| 546 | 454 | ||
| 547 | -bool SrsApiStreams::can_handle(const char* path, int length, const char** /*pchild*/) | 455 | +SrsGoApiStreams::~SrsGoApiStreams() |
| 548 | { | 456 | { |
| 549 | - return srs_path_equals("/streams", path, length); | ||
| 550 | } | 457 | } |
| 551 | 458 | ||
| 552 | -int SrsApiStreams::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | 459 | +int SrsGoApiStreams::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 553 | { | 460 | { |
| 554 | std::stringstream data; | 461 | std::stringstream data; |
| 555 | SrsStatistic* stat = SrsStatistic::instance(); | 462 | SrsStatistic* stat = SrsStatistic::instance(); |
| @@ -563,15 +470,14 @@ int SrsApiStreams::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -563,15 +470,14 @@ int SrsApiStreams::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 563 | << __SRS_JFIELD_ORG("streams", data.str()) | 470 | << __SRS_JFIELD_ORG("streams", data.str()) |
| 564 | << __SRS_JOBJECT_END; | 471 | << __SRS_JOBJECT_END; |
| 565 | 472 | ||
| 566 | - return res_json(skt, req, ss.str()); | 473 | + return srs_go_http_response_json(w, ss.str()); |
| 567 | } | 474 | } |
| 568 | 475 | ||
| 569 | -SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler) | ||
| 570 | - : SrsConnection(srs_server, client_stfd) | 476 | +SrsHttpApi::SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsGoHttpServeMux* m) |
| 477 | + : SrsConnection(svr, fd) | ||
| 571 | { | 478 | { |
| 479 | + mux = m; | ||
| 572 | parser = new SrsHttpParser(); | 480 | parser = new SrsHttpParser(); |
| 573 | - handler = _handler; | ||
| 574 | - requires_crossdomain = false; | ||
| 575 | } | 481 | } |
| 576 | 482 | ||
| 577 | SrsHttpApi::~SrsHttpApi() | 483 | SrsHttpApi::~SrsHttpApi() |
| @@ -628,7 +534,8 @@ int SrsHttpApi::do_cycle() | @@ -628,7 +534,8 @@ int SrsHttpApi::do_cycle() | ||
| 628 | SrsAutoFree(SrsHttpMessage, req); | 534 | SrsAutoFree(SrsHttpMessage, req); |
| 629 | 535 | ||
| 630 | // ok, handle http request. | 536 | // ok, handle http request. |
| 631 | - if ((ret = process_request(&skt, req)) != ERROR_SUCCESS) { | 537 | + SrsGoHttpResponseWriter writer(&skt); |
| 538 | + if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) { | ||
| 632 | return ret; | 539 | return ret; |
| 633 | } | 540 | } |
| 634 | } | 541 | } |
| @@ -636,46 +543,21 @@ int SrsHttpApi::do_cycle() | @@ -636,46 +543,21 @@ int SrsHttpApi::do_cycle() | ||
| 636 | return ret; | 543 | return ret; |
| 637 | } | 544 | } |
| 638 | 545 | ||
| 639 | -int SrsHttpApi::process_request(SrsStSocket* skt, SrsHttpMessage* req) | 546 | +int SrsHttpApi::process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) |
| 640 | { | 547 | { |
| 641 | int ret = ERROR_SUCCESS; | 548 | int ret = ERROR_SUCCESS; |
| 642 | 549 | ||
| 643 | - // parse uri to schema/server:port/path?query | ||
| 644 | - if ((ret = req->parse_uri()) != ERROR_SUCCESS) { | ||
| 645 | - return ret; | ||
| 646 | - } | ||
| 647 | - | ||
| 648 | srs_trace("HTTP %s %s, content-length=%"PRId64"", | 550 | srs_trace("HTTP %s %s, content-length=%"PRId64"", |
| 649 | - req->method_str().c_str(), req->url().c_str(), req->content_length()); | 551 | + r->method_str().c_str(), r->url().c_str(), r->content_length()); |
| 650 | 552 | ||
| 651 | - // TODO: maybe need to parse the url. | ||
| 652 | - std::string url = req->path(); | ||
| 653 | - | ||
| 654 | - SrsHttpHandlerMatch* p = NULL; | ||
| 655 | - if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) { | ||
| 656 | - srs_warn("failed to find the best match handler for url. ret=%d", ret); | ||
| 657 | - return ret; | 553 | + // use default server mux to serve http request. |
| 554 | + if ((ret = mux->serve_http(w, r)) != ERROR_SUCCESS) { | ||
| 555 | + if (!srs_is_client_gracefully_close(ret)) { | ||
| 556 | + srs_error("serve http msg failed. ret=%d", ret); | ||
| 658 | } | 557 | } |
| 659 | - | ||
| 660 | - // if success, p and pstart should be valid. | ||
| 661 | - srs_assert(p); | ||
| 662 | - srs_assert(p->handler); | ||
| 663 | - srs_assert(p->matched_url.length() <= url.length()); | ||
| 664 | - srs_info("best match handler, matched_url=%s", p->matched_url.c_str()); | ||
| 665 | - | ||
| 666 | - req->set_match(p); | ||
| 667 | - req->set_requires_crossdomain(requires_crossdomain); | ||
| 668 | - | ||
| 669 | - // use handler to process request. | ||
| 670 | - if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) { | ||
| 671 | - srs_warn("handler failed to process http request. ret=%d", ret); | ||
| 672 | return ret; | 558 | return ret; |
| 673 | } | 559 | } |
| 674 | 560 | ||
| 675 | - if (req->requires_crossdomain()) { | ||
| 676 | - requires_crossdomain = true; | ||
| 677 | - } | ||
| 678 | - | ||
| 679 | return ret; | 561 | return ret; |
| 680 | } | 562 | } |
| 681 | 563 |
| @@ -42,158 +42,130 @@ class SrsHttpHandler; | @@ -42,158 +42,130 @@ class SrsHttpHandler; | ||
| 42 | #include <srs_app_http.hpp> | 42 | #include <srs_app_http.hpp> |
| 43 | 43 | ||
| 44 | // for http root. | 44 | // for http root. |
| 45 | -class SrsApiRoot : public SrsHttpHandler | 45 | +class SrsGoApiRoot : public ISrsGoHttpHandler |
| 46 | { | 46 | { |
| 47 | public: | 47 | public: |
| 48 | - SrsApiRoot(); | ||
| 49 | - virtual ~SrsApiRoot(); | 48 | + SrsGoApiRoot(); |
| 49 | + virtual ~SrsGoApiRoot(); | ||
| 50 | public: | 50 | public: |
| 51 | - virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase); | ||
| 52 | -protected: | ||
| 53 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 54 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 51 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 55 | }; | 52 | }; |
| 56 | 53 | ||
| 57 | -class SrsApiApi : public SrsHttpHandler | 54 | +class SrsGoApiApi : public ISrsGoHttpHandler |
| 58 | { | 55 | { |
| 59 | public: | 56 | public: |
| 60 | - SrsApiApi(); | ||
| 61 | - virtual ~SrsApiApi(); | 57 | + SrsGoApiApi(); |
| 58 | + virtual ~SrsGoApiApi(); | ||
| 62 | public: | 59 | public: |
| 63 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 64 | -protected: | ||
| 65 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 60 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 66 | }; | 61 | }; |
| 67 | 62 | ||
| 68 | -class SrsApiV1 : public SrsHttpHandler | 63 | +class SrsGoApiV1 : public ISrsGoHttpHandler |
| 69 | { | 64 | { |
| 70 | public: | 65 | public: |
| 71 | - SrsApiV1(); | ||
| 72 | - virtual ~SrsApiV1(); | 66 | + SrsGoApiV1(); |
| 67 | + virtual ~SrsGoApiV1(); | ||
| 73 | public: | 68 | public: |
| 74 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 75 | -protected: | ||
| 76 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 69 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 77 | }; | 70 | }; |
| 78 | 71 | ||
| 79 | -class SrsApiRequests : public SrsHttpHandler | 72 | +class SrsGoApiVersion : public ISrsGoHttpHandler |
| 80 | { | 73 | { |
| 81 | public: | 74 | public: |
| 82 | - SrsApiRequests(); | ||
| 83 | - virtual ~SrsApiRequests(); | 75 | + SrsGoApiVersion(); |
| 76 | + virtual ~SrsGoApiVersion(); | ||
| 84 | public: | 77 | public: |
| 85 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 86 | -protected: | ||
| 87 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 78 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 88 | }; | 79 | }; |
| 89 | 80 | ||
| 90 | -class SrsApiVersion : public SrsHttpHandler | 81 | +class SrsGoApiSummaries : public ISrsGoHttpHandler |
| 91 | { | 82 | { |
| 92 | public: | 83 | public: |
| 93 | - SrsApiVersion(); | ||
| 94 | - virtual ~SrsApiVersion(); | 84 | + SrsGoApiSummaries(); |
| 85 | + virtual ~SrsGoApiSummaries(); | ||
| 95 | public: | 86 | public: |
| 96 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 97 | -protected: | ||
| 98 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 87 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 99 | }; | 88 | }; |
| 100 | 89 | ||
| 101 | -class SrsApiSummaries : public SrsHttpHandler | 90 | +class SrsGoApiRusages : public ISrsGoHttpHandler |
| 102 | { | 91 | { |
| 103 | public: | 92 | public: |
| 104 | - SrsApiSummaries(); | ||
| 105 | - virtual ~SrsApiSummaries(); | 93 | + SrsGoApiRusages(); |
| 94 | + virtual ~SrsGoApiRusages(); | ||
| 106 | public: | 95 | public: |
| 107 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 108 | -protected: | ||
| 109 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 96 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 110 | }; | 97 | }; |
| 111 | 98 | ||
| 112 | -class SrsApiRusages : public SrsHttpHandler | 99 | +class SrsGoApiSelfProcStats : public ISrsGoHttpHandler |
| 113 | { | 100 | { |
| 114 | public: | 101 | public: |
| 115 | - SrsApiRusages(); | ||
| 116 | - virtual ~SrsApiRusages(); | 102 | + SrsGoApiSelfProcStats(); |
| 103 | + virtual ~SrsGoApiSelfProcStats(); | ||
| 117 | public: | 104 | public: |
| 118 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 119 | -protected: | ||
| 120 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 105 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 121 | }; | 106 | }; |
| 122 | 107 | ||
| 123 | -class SrsApiSelfProcStats : public SrsHttpHandler | 108 | +class SrsGoApiSystemProcStats : public ISrsGoHttpHandler |
| 124 | { | 109 | { |
| 125 | public: | 110 | public: |
| 126 | - SrsApiSelfProcStats(); | ||
| 127 | - virtual ~SrsApiSelfProcStats(); | 111 | + SrsGoApiSystemProcStats(); |
| 112 | + virtual ~SrsGoApiSystemProcStats(); | ||
| 128 | public: | 113 | public: |
| 129 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 130 | -protected: | ||
| 131 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 114 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 132 | }; | 115 | }; |
| 133 | 116 | ||
| 134 | -class SrsApiSystemProcStats : public SrsHttpHandler | 117 | +class SrsGoApiMemInfos : public ISrsGoHttpHandler |
| 135 | { | 118 | { |
| 136 | public: | 119 | public: |
| 137 | - SrsApiSystemProcStats(); | ||
| 138 | - virtual ~SrsApiSystemProcStats(); | 120 | + SrsGoApiMemInfos(); |
| 121 | + virtual ~SrsGoApiMemInfos(); | ||
| 139 | public: | 122 | public: |
| 140 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 141 | -protected: | ||
| 142 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 123 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 143 | }; | 124 | }; |
| 144 | 125 | ||
| 145 | -class SrsApiMemInfos : public SrsHttpHandler | 126 | +class SrsGoApiAuthors : public ISrsGoHttpHandler |
| 146 | { | 127 | { |
| 147 | public: | 128 | public: |
| 148 | - SrsApiMemInfos(); | ||
| 149 | - virtual ~SrsApiMemInfos(); | 129 | + SrsGoApiAuthors(); |
| 130 | + virtual ~SrsGoApiAuthors(); | ||
| 150 | public: | 131 | public: |
| 151 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 152 | -protected: | ||
| 153 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 132 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 154 | }; | 133 | }; |
| 155 | 134 | ||
| 156 | -class SrsApiAuthors : public SrsHttpHandler | 135 | +class SrsGoApiRequests : public ISrsGoHttpHandler |
| 157 | { | 136 | { |
| 158 | public: | 137 | public: |
| 159 | - SrsApiAuthors(); | ||
| 160 | - virtual ~SrsApiAuthors(); | 138 | + SrsGoApiRequests(); |
| 139 | + virtual ~SrsGoApiRequests(); | ||
| 161 | public: | 140 | public: |
| 162 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 163 | -protected: | ||
| 164 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 141 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 165 | }; | 142 | }; |
| 166 | 143 | ||
| 167 | -class SrsApiVhosts : public SrsHttpHandler | 144 | +class SrsGoApiVhosts : public ISrsGoHttpHandler |
| 168 | { | 145 | { |
| 169 | public: | 146 | public: |
| 170 | - SrsApiVhosts(); | ||
| 171 | - virtual ~SrsApiVhosts(); | 147 | + SrsGoApiVhosts(); |
| 148 | + virtual ~SrsGoApiVhosts(); | ||
| 172 | public: | 149 | public: |
| 173 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 174 | -protected: | ||
| 175 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 150 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 176 | }; | 151 | }; |
| 177 | 152 | ||
| 178 | -class SrsApiStreams : public SrsHttpHandler | 153 | +class SrsGoApiStreams : public ISrsGoHttpHandler |
| 179 | { | 154 | { |
| 180 | public: | 155 | public: |
| 181 | - SrsApiStreams(); | ||
| 182 | - virtual ~SrsApiStreams(); | 156 | + SrsGoApiStreams(); |
| 157 | + virtual ~SrsGoApiStreams(); | ||
| 183 | public: | 158 | public: |
| 184 | - virtual bool can_handle(const char* path, int length, const char** pchild); | ||
| 185 | -protected: | ||
| 186 | - virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req); | 159 | + virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 187 | }; | 160 | }; |
| 188 | 161 | ||
| 189 | class SrsHttpApi : public SrsConnection | 162 | class SrsHttpApi : public SrsConnection |
| 190 | { | 163 | { |
| 191 | private: | 164 | private: |
| 192 | SrsHttpParser* parser; | 165 | SrsHttpParser* parser; |
| 193 | - SrsHttpHandler* handler; | ||
| 194 | - bool requires_crossdomain; | 166 | + SrsGoHttpServeMux* mux; |
| 195 | public: | 167 | public: |
| 196 | - SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler); | 168 | + SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsGoHttpServeMux* m); |
| 197 | virtual ~SrsHttpApi(); | 169 | virtual ~SrsHttpApi(); |
| 198 | public: | 170 | public: |
| 199 | virtual void kbps_resample(); | 171 | virtual void kbps_resample(); |
| @@ -204,7 +176,7 @@ public: | @@ -204,7 +176,7 @@ public: | ||
| 204 | protected: | 176 | protected: |
| 205 | virtual int do_cycle(); | 177 | virtual int do_cycle(); |
| 206 | private: | 178 | private: |
| 207 | - virtual int process_request(SrsStSocket* skt, SrsHttpMessage* req); | 179 | + virtual int process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); |
| 208 | }; | 180 | }; |
| 209 | 181 | ||
| 210 | #endif | 182 | #endif |
| @@ -550,11 +550,6 @@ int SrsHttpConn::process_request(SrsStSocket* skt, SrsHttpMessage* req) | @@ -550,11 +550,6 @@ int SrsHttpConn::process_request(SrsStSocket* skt, SrsHttpMessage* req) | ||
| 550 | { | 550 | { |
| 551 | int ret = ERROR_SUCCESS; | 551 | int ret = ERROR_SUCCESS; |
| 552 | 552 | ||
| 553 | - // parse uri to schema/server:port/path?query | ||
| 554 | - if ((ret = req->parse_uri()) != ERROR_SUCCESS) { | ||
| 555 | - return ret; | ||
| 556 | - } | ||
| 557 | - | ||
| 558 | srs_trace("HTTP %s %s, content-length=%"PRId64"", | 553 | srs_trace("HTTP %s %s, content-length=%"PRId64"", |
| 559 | req->method_str().c_str(), req->url().c_str(), req->content_length()); | 554 | req->method_str().c_str(), req->url().c_str(), req->content_length()); |
| 560 | 555 |
| @@ -330,7 +330,7 @@ SrsServer::SrsServer() | @@ -330,7 +330,7 @@ SrsServer::SrsServer() | ||
| 330 | // for some global instance is not ready now, | 330 | // for some global instance is not ready now, |
| 331 | // new these objects in initialize instead. | 331 | // new these objects in initialize instead. |
| 332 | #ifdef SRS_AUTO_HTTP_API | 332 | #ifdef SRS_AUTO_HTTP_API |
| 333 | - http_api_handler = NULL; | 333 | + http_api_mux = new SrsGoHttpServeMux(); |
| 334 | #endif | 334 | #endif |
| 335 | #ifdef SRS_AUTO_HTTP_SERVER | 335 | #ifdef SRS_AUTO_HTTP_SERVER |
| 336 | http_stream_handler = NULL; | 336 | http_stream_handler = NULL; |
| @@ -363,7 +363,7 @@ void SrsServer::destroy() | @@ -363,7 +363,7 @@ void SrsServer::destroy() | ||
| 363 | #endif | 363 | #endif |
| 364 | 364 | ||
| 365 | #ifdef SRS_AUTO_HTTP_API | 365 | #ifdef SRS_AUTO_HTTP_API |
| 366 | - srs_freep(http_api_handler); | 366 | + srs_freep(http_api_mux); |
| 367 | #endif | 367 | #endif |
| 368 | 368 | ||
| 369 | #ifdef SRS_AUTO_HTTP_SERVER | 369 | #ifdef SRS_AUTO_HTTP_SERVER |
| @@ -415,8 +415,52 @@ int SrsServer::initialize() | @@ -415,8 +415,52 @@ int SrsServer::initialize() | ||
| 415 | kbps->set_io(NULL, NULL); | 415 | kbps->set_io(NULL, NULL); |
| 416 | 416 | ||
| 417 | #ifdef SRS_AUTO_HTTP_API | 417 | #ifdef SRS_AUTO_HTTP_API |
| 418 | - srs_assert(!http_api_handler); | ||
| 419 | - http_api_handler = SrsHttpHandler::create_http_api(); | 418 | + if ((ret = http_api_mux->initialize()) != ERROR_SUCCESS) { |
| 419 | + return ret; | ||
| 420 | + } | ||
| 421 | +#endif | ||
| 422 | + | ||
| 423 | +#ifdef SRS_AUTO_HTTP_API | ||
| 424 | + srs_assert(http_api_mux); | ||
| 425 | + if ((ret = http_api_mux->handle("/", new SrsGoApiRoot())) != ERROR_SUCCESS) { | ||
| 426 | + return ret; | ||
| 427 | + } | ||
| 428 | + if ((ret = http_api_mux->handle("/api", new SrsGoApiApi())) != ERROR_SUCCESS) { | ||
| 429 | + return ret; | ||
| 430 | + } | ||
| 431 | + if ((ret = http_api_mux->handle("/api/v1", new SrsGoApiV1())) != ERROR_SUCCESS) { | ||
| 432 | + return ret; | ||
| 433 | + } | ||
| 434 | + if ((ret = http_api_mux->handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) { | ||
| 435 | + return ret; | ||
| 436 | + } | ||
| 437 | + if ((ret = http_api_mux->handle("/api/v1/summaries", new SrsGoApiSummaries())) != ERROR_SUCCESS) { | ||
| 438 | + return ret; | ||
| 439 | + } | ||
| 440 | + if ((ret = http_api_mux->handle("/api/v1/rusages", new SrsGoApiRusages())) != ERROR_SUCCESS) { | ||
| 441 | + return ret; | ||
| 442 | + } | ||
| 443 | + if ((ret = http_api_mux->handle("/api/v1/self_proc_stats", new SrsGoApiSelfProcStats())) != ERROR_SUCCESS) { | ||
| 444 | + return ret; | ||
| 445 | + } | ||
| 446 | + if ((ret = http_api_mux->handle("/api/v1/system_proc_stats", new SrsGoApiSystemProcStats())) != ERROR_SUCCESS) { | ||
| 447 | + return ret; | ||
| 448 | + } | ||
| 449 | + if ((ret = http_api_mux->handle("/api/v1/meminfos", new SrsGoApiMemInfos())) != ERROR_SUCCESS) { | ||
| 450 | + return ret; | ||
| 451 | + } | ||
| 452 | + if ((ret = http_api_mux->handle("/api/v1/authors", new SrsGoApiAuthors())) != ERROR_SUCCESS) { | ||
| 453 | + return ret; | ||
| 454 | + } | ||
| 455 | + if ((ret = http_api_mux->handle("/api/v1/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) { | ||
| 456 | + return ret; | ||
| 457 | + } | ||
| 458 | + if ((ret = http_api_mux->handle("/api/v1/vhosts", new SrsGoApiVhosts())) != ERROR_SUCCESS) { | ||
| 459 | + return ret; | ||
| 460 | + } | ||
| 461 | + if ((ret = http_api_mux->handle("/api/v1/streams", new SrsGoApiStreams())) != ERROR_SUCCESS) { | ||
| 462 | + return ret; | ||
| 463 | + } | ||
| 420 | #endif | 464 | #endif |
| 421 | #ifdef SRS_AUTO_HTTP_SERVER | 465 | #ifdef SRS_AUTO_HTTP_SERVER |
| 422 | srs_assert(!http_stream_handler); | 466 | srs_assert(!http_stream_handler); |
| @@ -431,12 +475,6 @@ int SrsServer::initialize() | @@ -431,12 +475,6 @@ int SrsServer::initialize() | ||
| 431 | ingester = new SrsIngester(); | 475 | ingester = new SrsIngester(); |
| 432 | #endif | 476 | #endif |
| 433 | 477 | ||
| 434 | -#ifdef SRS_AUTO_HTTP_API | ||
| 435 | - if ((ret = http_api_handler->initialize()) != ERROR_SUCCESS) { | ||
| 436 | - return ret; | ||
| 437 | - } | ||
| 438 | -#endif | ||
| 439 | - | ||
| 440 | #ifdef SRS_AUTO_HTTP_SERVER | 478 | #ifdef SRS_AUTO_HTTP_SERVER |
| 441 | if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) { | 479 | if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) { |
| 442 | return ret; | 480 | return ret; |
| @@ -896,7 +934,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) | @@ -896,7 +934,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) | ||
| 896 | conn = new SrsRtmpConn(this, client_stfd); | 934 | conn = new SrsRtmpConn(this, client_stfd); |
| 897 | } else if (type == SrsListenerHttpApi) { | 935 | } else if (type == SrsListenerHttpApi) { |
| 898 | #ifdef SRS_AUTO_HTTP_API | 936 | #ifdef SRS_AUTO_HTTP_API |
| 899 | - conn = new SrsHttpApi(this, client_stfd, http_api_handler); | 937 | + conn = new SrsHttpApi(this, client_stfd, http_api_mux); |
| 900 | #else | 938 | #else |
| 901 | srs_warn("close http client for server not support http-api"); | 939 | srs_warn("close http client for server not support http-api"); |
| 902 | srs_close_stfd(client_stfd); | 940 | srs_close_stfd(client_stfd); |
| @@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 38 | 38 | ||
| 39 | class SrsServer; | 39 | class SrsServer; |
| 40 | class SrsConnection; | 40 | class SrsConnection; |
| 41 | +class SrsGoHttpServeMux; | ||
| 41 | class SrsHttpHandler; | 42 | class SrsHttpHandler; |
| 42 | class SrsIngester; | 43 | class SrsIngester; |
| 43 | class SrsHttpHeartbeat; | 44 | class SrsHttpHeartbeat; |
| @@ -116,7 +117,7 @@ class SrsServer : public ISrsReloadHandler | @@ -116,7 +117,7 @@ class SrsServer : public ISrsReloadHandler | ||
| 116 | { | 117 | { |
| 117 | private: | 118 | private: |
| 118 | #ifdef SRS_AUTO_HTTP_API | 119 | #ifdef SRS_AUTO_HTTP_API |
| 119 | - SrsHttpHandler* http_api_handler; | 120 | + SrsGoHttpServeMux* http_api_mux; |
| 120 | #endif | 121 | #endif |
| 121 | #ifdef SRS_AUTO_HTTP_SERVER | 122 | #ifdef SRS_AUTO_HTTP_SERVER |
| 122 | SrsHttpHandler* http_stream_handler; | 123 | SrsHttpHandler* http_stream_handler; |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 95 | 34 | +#define VERSION_REVISION 96 |
| 35 | 35 | ||
| 36 | // server info. | 36 | // server info. |
| 37 | #define RTMP_SIG_SRS_KEY "SRS" | 37 | #define RTMP_SIG_SRS_KEY "SRS" |
| @@ -204,6 +204,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -204,6 +204,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 204 | #define ERROR_AAC_DATA_INVALID 3048 | 204 | #define ERROR_AAC_DATA_INVALID 3048 |
| 205 | #define ERROR_HTTP_STATUS_INVLIAD 3049 | 205 | #define ERROR_HTTP_STATUS_INVLIAD 3049 |
| 206 | 206 | ||
| 207 | +/////////////////////////////////////////////////////// | ||
| 208 | +// HTTP protocol error. | ||
| 209 | +/////////////////////////////////////////////////////// | ||
| 210 | +#define ERROR_HTTP_PATTERN_EMPTY 4000 | ||
| 211 | +#define ERROR_HTTP_PATTERN_DUPLICATED 4001 | ||
| 212 | +#define ERROR_HTTP_URL_NOT_CLEAN 4002 | ||
| 213 | +#define ERROR_HTTP_CONTENT_LENGTH 4003 | ||
| 214 | + | ||
| 207 | /** | 215 | /** |
| 208 | * whether the error code is an system control error. | 216 | * whether the error code is an system control error. |
| 209 | */ | 217 | */ |
-
请 注册 或 登录 后发表评论