winlin

for bug #277, refine http api refer to go http-framework. 2.0.97

@@ -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;
@@ -859,6 +1350,13 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg) @@ -859,6 +1350,13 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg)
859 srs_freep(msg); 1350 srs_freep(msg);
860 return ret; 1351 return ret;
861 } 1352 }
  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 + }
862 1360
863 // parse ok, return the msg. 1361 // parse ok, return the msg.
864 *ppmsg = msg; 1362 *ppmsg = msg;
@@ -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
@@ -82,25 +56,19 @@ int SrsApiRoot::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) @@ -82,25 +56,19 @@ int SrsApiRoot::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
82 << __SRS_JFIELD_STR("api", "the api root") 56 << __SRS_JFIELD_STR("api", "the api root")
83 << __SRS_JOBJECT_END 57 << __SRS_JOBJECT_END
84 << __SRS_JOBJECT_END; 58 << __SRS_JOBJECT_END;
85 -  
86 - return res_json(skt, req, ss.str());  
87 -}  
88 -  
89 -SrsApiApi::SrsApiApi()  
90 -{  
91 - handlers.push_back(new SrsApiV1()); 59 +
  60 + return srs_go_http_response_json(w, ss.str());
92 } 61 }
93 62
94 -SrsApiApi::~SrsApiApi() 63 +SrsGoApiApi::SrsGoApiApi()
95 { 64 {
96 } 65 }
97 66
98 -bool SrsApiApi::can_handle(const char* path, int length, const char** /*pchild*/) 67 +SrsGoApiApi::~SrsGoApiApi()
99 { 68 {
100 - return srs_path_equals("/api", path, length);  
101 } 69 }
102 70
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
@@ -110,34 +78,19 @@ int SrsApiApi::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) @@ -110,34 +78,19 @@ int SrsApiApi::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
110 << __SRS_JFIELD_STR("v1", "the api version 1.0") 78 << __SRS_JFIELD_STR("v1", "the api version 1.0")
111 << __SRS_JOBJECT_END 79 << __SRS_JOBJECT_END
112 << __SRS_JOBJECT_END; 80 << __SRS_JOBJECT_END;
113 -  
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()); 81 +
  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()); 113 + return srs_go_http_response_json(w, ss.str());
161 } 114 }
162 115
163 -SrsApiRequests::SrsApiRequests() 116 +SrsGoApiVersion::SrsGoApiVersion()
164 { 117 {
165 } 118 }
166 119
167 -SrsApiRequests::~SrsApiRequests() 120 +SrsGoApiVersion::~SrsGoApiVersion()
168 { 121 {
169 } 122 }
170 123
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 -{  
229 -}  
230 -  
231 -SrsApiVersion::~SrsApiVersion()  
232 -{  
233 -}  
234 -  
235 -bool SrsApiVersion::can_handle(const char* path, int length, const char** /*pchild*/)  
236 -{  
237 - return srs_path_equals("/versions", path, length);  
238 -}  
239 -  
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());  
255 -}  
256 -  
257 -SrsApiSummaries::SrsApiSummaries()  
258 -{ 138 + return srs_go_http_response_json(w, ss.str());
259 } 139 }
260 140
261 -SrsApiSummaries::~SrsApiSummaries() 141 +SrsGoApiSummaries::SrsGoApiSummaries()
262 { 142 {
263 } 143 }
264 144
265 -bool SrsApiSummaries::can_handle(const char* path, int length, const char** /*pchild*/) 145 +SrsGoApiSummaries::~SrsGoApiSummaries()
266 { 146 {
267 - return srs_path_equals("/summaries", path, length);  
268 } 147 }
269 148
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()); 299 + return srs_go_http_response_json(w, ss.str());
436 } 300 }
437 301
438 -SrsApiMemInfos::SrsApiMemInfos() 302 +SrsGoApiMemInfos::SrsGoApiMemInfos()
439 { 303 {
440 } 304 }
441 305
442 -SrsApiMemInfos::~SrsApiMemInfos() 306 +SrsGoApiMemInfos::~SrsGoApiMemInfos()
443 { 307 {
444 } 308 }
445 309
446 -bool SrsApiMemInfos::can_handle(const char* path, int length, const char** /*pchild*/)  
447 -{  
448 - return srs_path_equals("/meminfos", path, length);  
449 -}  
450 -  
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());
  361 +}
  362 +
  363 +SrsGoApiRequests::SrsGoApiRequests()
  364 +{
  365 +}
  366 +
  367 +SrsGoApiRequests::~SrsGoApiRequests()
  368 +{
507 } 369 }
508 370
509 -SrsApiVhosts::SrsApiVhosts() 371 +int SrsGoApiRequests::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
510 { 372 {
  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());
511 } 422 }
512 423
513 -SrsApiVhosts::~SrsApiVhosts() 424 +SrsGoApiVhosts::SrsGoApiVhosts()
514 { 425 {
515 } 426 }
516 427
517 -bool SrsApiVhosts::can_handle(const char* path, int length, const char** /*pchild*/) 428 +SrsGoApiVhosts::~SrsGoApiVhosts()
518 { 429 {
519 - return srs_path_equals("/vhosts", path, length);  
520 } 430 }
521 431
522 -int SrsApiVhosts::do_process_request(SrsStSocket* skt, SrsHttpMessage* req) 432 +int SrsGoApiVhosts::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
523 { 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()); 448 + return srs_go_http_response_json(w, ss.str());
537 } 449 }
538 450
539 -SrsApiStreams::SrsApiStreams() 451 +SrsGoApiStreams::SrsGoApiStreams()
540 { 452 {
541 } 453 }
542 454
543 -SrsApiStreams::~SrsApiStreams() 455 +SrsGoApiStreams::~SrsGoApiStreams()
544 { 456 {
545 } 457 }
546 458
547 -bool SrsApiStreams::can_handle(const char* path, int length, const char** /*pchild*/)  
548 -{  
549 - return srs_path_equals("/streams", path, length);  
550 -}  
551 -  
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 -  
643 - // parse uri to schema/server:port/path?query  
644 - if ((ret = req->parse_uri()) != ERROR_SUCCESS) {  
645 - return ret;  
646 - }  
647 549
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());  
650 -  
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;  
658 - } 551 + r->method_str().c_str(), r->url().c_str(), r->content_length());
659 552
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); 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);
  557 + }
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
@@ -549,11 +549,6 @@ int SrsHttpConn::do_cycle() @@ -549,11 +549,6 @@ int SrsHttpConn::do_cycle()
549 int SrsHttpConn::process_request(SrsStSocket* skt, SrsHttpMessage* req) 549 int SrsHttpConn::process_request(SrsStSocket* skt, SrsHttpMessage* req)
550 { 550 {
551 int ret = ERROR_SUCCESS; 551 int ret = ERROR_SUCCESS;
552 -  
553 - // parse uri to schema/server:port/path?query  
554 - if ((ret = req->parse_uri()) != ERROR_SUCCESS) {  
555 - return ret;  
556 - }  
557 552
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());
@@ -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);
@@ -430,12 +474,6 @@ int SrsServer::initialize() @@ -430,12 +474,6 @@ int SrsServer::initialize()
430 srs_assert(!ingester); 474 srs_assert(!ingester);
431 ingester = new SrsIngester(); 475 ingester = new SrsIngester();
432 #endif 476 #endif
433 -  
434 -#ifdef SRS_AUTO_HTTP_API  
435 - if ((ret = http_api_handler->initialize()) != ERROR_SUCCESS) {  
436 - return ret;  
437 - }  
438 -#endif  
439 477
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) {
@@ -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 */