SrsHttpApi类
app/srs_app_http_api.hpp
app/srs_app_http_api.cpp
class SrsHttpApi : virtual public SrsConnection, virtual public ISrsReloadHandler
{
private:
    SrsHttpParser* parser;
    SrsHttpCorsMux* cors;
    SrsHttpServeMux* mux;
public:
    SrsHttpApi(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m, std::string cip);
    virtual ~SrsHttpApi();
// interface IKbpsDelta
public:
    virtual void resample();
    virtual int64_t get_send_bytes_delta();
    virtual int64_t get_recv_bytes_delta();
    virtual void cleanup();
protected:
    virtual int do_cycle();
private:
    virtual int process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
// interface ISrsReloadHandler
public:
    virtual int on_reload_http_api_crossdomain();
};
int SrsHttpApi::do_cycle()
{
    int ret = ERROR_SUCCESS;
    
    srs_trace("api get peer ip success. ip=%s", ip.c_str());
    
    // initialize parser
    if ((ret = parser->initialize(HTTP_REQUEST, true)) != ERROR_SUCCESS) {
        srs_error("api initialize http parser failed. ret=%d", ret);
        return ret;
    }
    
    // set the recv timeout, for some clients never disconnect the connection.
    // @see https://github.com/ossrs/srs/issues/398
    skt->set_recv_timeout(SRS_HTTP_RECV_TMMS);
    
    // initialize the cors, which will proxy to mux.
    bool crossdomain_enabled = _srs_config->get_http_api_crossdomain();
    if ((ret = cors->initialize(mux, crossdomain_enabled)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // process http messages.
    while(!disposed) {
        ISrsHttpMessage* req = NULL;
        
        // get a http message
        if ((ret = parser->parse_message(skt, this, &req)) != ERROR_SUCCESS) {
            return ret;
        }
        
        // if SUCCESS, always NOT-NULL.
        srs_assert(req);
        
        // always free it in this scope.
        SrsAutoFree(ISrsHttpMessage, req);
        
        // ok, handle http request.
        SrsHttpResponseWriter writer(skt);
        if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) {
            return ret;
        }
        
        // read all rest bytes in request body.
        char buf[SRS_HTTP_READ_CACHE_BYTES];
        ISrsHttpResponseReader* br = req->body_reader();
        while (!br->eof()) {
            if ((ret = br->read(buf, SRS_HTTP_READ_CACHE_BYTES, NULL)) != ERROR_SUCCESS) {
                return ret;
            }
        }
        
        // donot keep alive, disconnect it.
        // @see https://github.com/ossrs/srs/issues/399
        if (!req->is_keep_alive()) {
            break;
        }
    }
    
    return ret;
}

 1. call SrsHttpParser::parse_message(skt, this, &req)得到 ISrsHttpMessage类型的 req

 2.  SrsHttpResponseWriter writer(skt); process_request(&writer, req)

int SrsHttpParser::parse_message(ISrsProtocolReaderWriter* io, SrsConnection* conn, ISrsHttpMessage** ppmsg)
{
    *ppmsg = NULL;
    
    int ret = ERROR_SUCCESS;
    
    // reset request data.
    field_name = "";
    field_value = "";
    expect_field_name = true;
    state = SrsHttpParseStateInit;
    header = http_parser();
    url = "";
    headers.clear();
    header_parsed = 0;
    
    // do parse
    if ((ret = parse_message_imp(io)) != ERROR_SUCCESS) {
        if (!srs_is_client_gracefully_close(ret)) {
            srs_error("parse http msg failed. ret=%d", ret);
        }
        return ret;
    }
    
    // create msg
    SrsHttpMessage* msg = new SrsHttpMessage(io, conn);
    
    // initalize http msg, parse url.
    if ((ret = msg->update(url, jsonp, &header, buffer, headers)) != ERROR_SUCCESS) {
        srs_error("initialize http msg failed. ret=%d", ret);
        srs_freep(msg);
        return ret;
    }
    
    // parse ok, return the msg.
    *ppmsg = msg;
    
    return ret;
}
int SrsHttpParser::parse_message_imp(ISrsProtocolReaderWriter* io)
{
    int ret = ERROR_SUCCESS;
    
    while (true) {
        ssize_t nparsed = 0;
        
        // when got entire http header, parse it.
        // @see https://github.com/ossrs/srs/issues/400
        char* start = buffer->bytes();
        char* end = start + buffer->size();
        for (char* p = start; p <= end - 4; p++) {
            // SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
            if (p[0] == SRS_CONSTS_CR && p[1] == SRS_CONSTS_LF && p[2] == SRS_CONSTS_CR && p[3] == SRS_CONSTS_LF) {
                nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size());
                srs_info("buffer=%d, nparsed=%d, header=%d", buffer->size(), (int)nparsed, header_parsed);
                break;
            }
        }
        
        // consume the parsed bytes.
        if (nparsed && header_parsed) {
            buffer->read_slice(header_parsed);
        }
        
        // ok atleast header completed,
        // never wait for body completed, for maybe chunked.
        if (state == SrsHttpParseStateHeaderComplete || state == SrsHttpParseStateMessageComplete) {
            break;
        }
        
        // when nothing parsed, read more to parse.
        if (nparsed == 0) {
            // when requires more, only grow 1bytes, but the buffer will cache more.
            if ((ret = buffer->grow(io, buffer->size() + 1)) != ERROR_SUCCESS) {
                if (!srs_is_client_gracefully_close(ret)) {
                    srs_error("read body from server failed. ret=%d", ret);
                }
                return ret;
            }
        }
    }
    
    // parse last header.
    if (!field_name.empty() && !field_value.empty()) {
        headers.push_back(std::make_pair(field_name, field_value));
    }
    
    return ret;
}
1. parse_message_imp函数里调用
http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size());执行http parser
在此过程中会回调 settings中的函数保存此次解析的结果
parse_message_imp函数解析的是http头部的数据
2. msg->update(url, jsonp, &header, buffer, headers))
int SrsHttpMessage::update(string url, bool allow_jsonp, http_parser* header, SrsFastStream* body, vector<SrsHttpHeaderField>& headers)
{
    int ret = ERROR_SUCCESS;
    
    _url = url;
    _header = *header;
    _headers = headers;
    
    // whether chunked.
    std::string transfer_encoding = get_request_header("Transfer-Encoding");
    chunked = (transfer_encoding == "chunked");
    
    // whether keep alive.
    keep_alive = http_should_keep_alive(header);
    
    // set the buffer.
    if ((ret = _body->initialize(body)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // parse uri from url.
    std::string host = get_request_header("Host");
    
    // use server public ip when no host specified.
    // to make telnet happy.
    if (host.empty()) {
        host= srs_get_public_internet_address();
    }
    
    // parse uri to schema/server:port/path?query
    std::string uri = "http://" + host + _url;
    if ((ret = _uri->initialize(uri)) != ERROR_SUCCESS) {
        return ret;
    }
    
    // parse ext.
    _ext = srs_path_filext(_uri->get_path());
    
    // parse query string.
    srs_parse_query_string(_uri->get_query(), _query);
    
    // parse jsonp request message.
    if (allow_jsonp) {
        if (!query_get("callback").empty()) {
            jsonp = true;
        }
        if (jsonp) {
            jsonp_method = query_get("method");
        }
    }
    
    return ret;
}
int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
    int ret = ERROR_SUCCESS;
    
    SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(r);
    srs_assert(hm);
    
    srs_trace("HTTP API %s %s, content-length=%" PRId64 ", chunked=%d/%d",
              r->method_str().c_str(), r->url().c_str(), r->content_length(),
              hm->is_chunked(), hm->is_infinite_chunked());
    
    // use cors server mux to serve http request, which will proxy to mux.
    if ((ret = cors->serve_http(w, r)) != ERROR_SUCCESS) {
        if (!srs_is_client_gracefully_close(ret)) {
            srs_error("serve http msg failed. ret=%d", ret);
        }
        return ret;
    }
    
    return ret;
}

在 SrsServer:: fd2conn中看到

conn = new SrsHttpApi(this, stfd, http_api_mux, ip);
所以请求会有
http_api_mux变量处理,
http_api_mux的请求路由设置是在SrsServer::http_handle函数,调用位置 srs_main_server.cpp:434 run_master函数
[zk2013@localhost src]$ grep -Fnr "http_handle"
app/srs_app_server.cpp:752:int SrsServer::http_handle()
app/srs_app_server.hpp:290:    virtual int http_handle();
main/srs_main_server.cpp:434:    if ((ret = svr->http_handle()) != ERROR_SUCCESS) {
int run_master(SrsServer* svr)
{
    int ret = ERROR_SUCCESS;
    
    if ((ret = svr->initialize_st()) != ERROR_SUCCESS) {
        return ret;
    }
    
    if ((ret = svr->initialize_signal()) != ERROR_SUCCESS) {
        return ret;
    }
    
    if ((ret = svr->acquire_pid_file()) != ERROR_SUCCESS) {
        return ret;
    }
    // 开启 rtmp, http, caster 监听
    if ((ret = svr->listen()) != ERROR_SUCCESS) {
        return ret;
    }
    
    if ((ret = svr->register_signal()) != ERROR_SUCCESS) {
        return ret;
    }
    // 设置 http api的路由处理
    if ((ret = svr->http_handle()) != ERROR_SUCCESS) {
        return ret;
    }
    
    if ((ret = svr->ingest()) != ERROR_SUCCESS) {
        return ret;
    }
    
    if ((ret = svr->cycle()) != ERROR_SUCCESS) {
        return ret;
    }
    
    return 0;
}

 

int SrsServer::http_handle()
{
    int ret = ERROR_SUCCESS;
    
    srs_assert(http_api_mux);
    if ((ret = http_api_mux->handle("/", new SrsHttpNotFoundHandler())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/", new SrsGoApiApi())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/", new SrsGoApiV1())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/versions", new SrsGoApiVersion())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/summaries", new SrsGoApiSummaries())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/rusages", new SrsGoApiRusages())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/self_proc_stats", new SrsGoApiSelfProcStats())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/system_proc_stats", new SrsGoApiSystemProcStats())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/meminfos", new SrsGoApiMemInfos())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/authors", new SrsGoApiAuthors())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/features", new SrsGoApiFeatures())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/vhosts/", new SrsGoApiVhosts())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/streams/", new SrsGoApiStreams())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/clients/", new SrsGoApiClients())) != ERROR_SUCCESS) {
        return ret;
    }
    if ((ret = http_api_mux->handle("/api/v1/raw", new SrsGoApiRaw(this))) != ERROR_SUCCESS) {
        return ret;
    }
    
    // test the request info.
    if ((ret = http_api_mux->handle("/api/v1/tests/requests", new SrsGoApiRequests())) != ERROR_SUCCESS) {
        return ret;
    }
    // test the error code response.
    if ((ret = http_api_mux->handle("/api/v1/tests/errors", new SrsGoApiError())) != ERROR_SUCCESS) {
        return ret;
    }
    // test the redirect mechenism.
    if ((ret = http_api_mux->handle("/api/v1/tests/redirects", new SrsHttpRedirectHandler("/api/v1/tests/errors", SRS_CONSTS_HTTP_MovedPermanently))) != ERROR_SUCCESS) {
        return ret;
    }
    // test the http vhost.
    if ((ret = http_api_mux->handle("error.srs.com/api/v1/tests/errors", new SrsGoApiError())) != ERROR_SUCCESS) {
        return ret;
    }
    
    // TODO: FIXME: for console.
    // TODO: FIXME: support reload.
    std::string dir = _srs_config->get_http_stream_dir() + "/console";
    if ((ret = http_api_mux->handle("/console/", new SrsHttpFileServer(dir))) != ERROR_SUCCESS) {
        srs_error("http: mount console dir=%s failed. ret=%d", dir.c_str(), ret);
        return ret;
    }
    srs_trace("http: api mount /console to %s", dir.c_str());
    
    return ret;
}