mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for bug #277, refine http api refer to go http-framework. 2.0.97
This commit is contained in:
parent
33efeeb399
commit
9bbbaad288
10 changed files with 1004 additions and 395 deletions
|
@ -510,6 +510,7 @@ Supported operating systems and hardware:
|
||||||
|
|
||||||
## History
|
## History
|
||||||
|
|
||||||
|
* 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
|
||||||
* 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
|
* 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
|
||||||
* 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
|
* 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
|
||||||
* 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
|
* 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)
|
||||||
return equals;
|
return equals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data)
|
||||||
|
{
|
||||||
|
w->header()->set_content_length(data.length());
|
||||||
|
w->header()->set_content_type("application/json;charset=utf-8");
|
||||||
|
|
||||||
|
return w->write((char*)data.data(), data.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the status text of code.
|
||||||
|
string srs_generate_status_text(int status)
|
||||||
|
{
|
||||||
|
static std::map<int, std::string> _status_map;
|
||||||
|
if (_status_map.empty()) {
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Continue ] = SRS_CONSTS_HTTP_Continue_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_SwitchingProtocols ] = SRS_CONSTS_HTTP_SwitchingProtocols_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_OK ] = SRS_CONSTS_HTTP_OK_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Created ] = SRS_CONSTS_HTTP_Created_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Accepted ] = SRS_CONSTS_HTTP_Accepted_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_NonAuthoritativeInformation ] = SRS_CONSTS_HTTP_NonAuthoritativeInformation_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_NoContent ] = SRS_CONSTS_HTTP_NoContent_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_ResetContent ] = SRS_CONSTS_HTTP_ResetContent_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_PartialContent ] = SRS_CONSTS_HTTP_PartialContent_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_MultipleChoices ] = SRS_CONSTS_HTTP_MultipleChoices_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_MovedPermanently ] = SRS_CONSTS_HTTP_MovedPermanently_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Found ] = SRS_CONSTS_HTTP_Found_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_SeeOther ] = SRS_CONSTS_HTTP_SeeOther_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_NotModified ] = SRS_CONSTS_HTTP_NotModified_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_UseProxy ] = SRS_CONSTS_HTTP_UseProxy_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_TemporaryRedirect ] = SRS_CONSTS_HTTP_TemporaryRedirect_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_BadRequest ] = SRS_CONSTS_HTTP_BadRequest_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Unauthorized ] = SRS_CONSTS_HTTP_Unauthorized_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_PaymentRequired ] = SRS_CONSTS_HTTP_PaymentRequired_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Forbidden ] = SRS_CONSTS_HTTP_Forbidden_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_NotFound ] = SRS_CONSTS_HTTP_NotFound_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_MethodNotAllowed ] = SRS_CONSTS_HTTP_MethodNotAllowed_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_NotAcceptable ] = SRS_CONSTS_HTTP_NotAcceptable_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_ProxyAuthenticationRequired ] = SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_RequestTimeout ] = SRS_CONSTS_HTTP_RequestTimeout_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Conflict ] = SRS_CONSTS_HTTP_Conflict_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_Gone ] = SRS_CONSTS_HTTP_Gone_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_LengthRequired ] = SRS_CONSTS_HTTP_LengthRequired_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_PreconditionFailed ] = SRS_CONSTS_HTTP_PreconditionFailed_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_RequestEntityTooLarge ] = SRS_CONSTS_HTTP_RequestEntityTooLarge_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_RequestURITooLarge ] = SRS_CONSTS_HTTP_RequestURITooLarge_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_UnsupportedMediaType ] = SRS_CONSTS_HTTP_UnsupportedMediaType_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable ] = SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_ExpectationFailed ] = SRS_CONSTS_HTTP_ExpectationFailed_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_InternalServerError ] = SRS_CONSTS_HTTP_InternalServerError_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_NotImplemented ] = SRS_CONSTS_HTTP_NotImplemented_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_BadGateway ] = SRS_CONSTS_HTTP_BadGateway_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_ServiceUnavailable ] = SRS_CONSTS_HTTP_ServiceUnavailable_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_GatewayTimeout ] = SRS_CONSTS_HTTP_GatewayTimeout_str ;
|
||||||
|
_status_map[SRS_CONSTS_HTTP_HTTPVersionNotSupported ] = SRS_CONSTS_HTTP_HTTPVersionNotSupported_str ;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string status_text;
|
||||||
|
if (_status_map.find(status) == _status_map.end()) {
|
||||||
|
status_text = "Status Unknown";
|
||||||
|
} else {
|
||||||
|
status_text = _status_map[status];
|
||||||
|
}
|
||||||
|
|
||||||
|
return status_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bodyAllowedForStatus reports whether a given response status code
|
||||||
|
// permits a body. See RFC2616, section 4.4.
|
||||||
|
bool srs_go_http_body_allowd(int status)
|
||||||
|
{
|
||||||
|
if (status >= 100 && status <= 199) {
|
||||||
|
return false;
|
||||||
|
} else if (status == 204 || status == 304) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetectContentType implements the algorithm described
|
||||||
|
// at http://mimesniff.spec.whatwg.org/ to determine the
|
||||||
|
// Content-Type of the given data. It considers at most the
|
||||||
|
// first 512 bytes of data. DetectContentType always returns
|
||||||
|
// a valid MIME type: if it cannot determine a more specific one, it
|
||||||
|
// returns "application/octet-stream".
|
||||||
|
string srs_go_http_detect(char* data, int size)
|
||||||
|
{
|
||||||
|
return "application/octet-stream"; // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error replies to the request with the specified error message and HTTP code.
|
||||||
|
// The error message should be plain text.
|
||||||
|
int srs_go_http_error(ISrsGoHttpResponseWriter* w, int code, string error)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
w->header()->set_content_type("text/plain; charset=utf-8");
|
||||||
|
w->header()->set_content_length(error.length());
|
||||||
|
w->write_header(code);
|
||||||
|
w->write((char*)error.data(), (int)error.length());
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpHeader::SrsGoHttpHeader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpHeader::~SrsGoHttpHeader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsGoHttpHeader::set(string key, string value)
|
||||||
|
{
|
||||||
|
headers[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string SrsGoHttpHeader::get(string key)
|
||||||
|
{
|
||||||
|
std::string v;
|
||||||
|
|
||||||
|
if (headers.find(key) != headers.end()) {
|
||||||
|
v = headers[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t SrsGoHttpHeader::content_length()
|
||||||
|
{
|
||||||
|
std::string cl = get("Content-Length");
|
||||||
|
|
||||||
|
if (cl.empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int64_t)::atof(cl.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsGoHttpHeader::set_content_length(int64_t size)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "%"PRId64, size);
|
||||||
|
set("Content-Length", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
string SrsGoHttpHeader::content_type()
|
||||||
|
{
|
||||||
|
return get("Content-Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsGoHttpHeader::set_content_type(string ct)
|
||||||
|
{
|
||||||
|
set("Content-Type", ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsGoHttpHeader::write(stringstream& ss)
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string>::iterator it;
|
||||||
|
for (it = headers.begin(); it != headers.end(); ++it) {
|
||||||
|
ss << it->first << ": " << it->second << __SRS_CRLF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsGoHttpResponseWriter::ISrsGoHttpResponseWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsGoHttpResponseWriter::~ISrsGoHttpResponseWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsGoHttpHandler::ISrsGoHttpHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsGoHttpHandler::~ISrsGoHttpHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpRedirectHandler::SrsGoHttpRedirectHandler(string u, int c)
|
||||||
|
{
|
||||||
|
url = u;
|
||||||
|
code = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpRedirectHandler::~SrsGoHttpRedirectHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpRedirectHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
// TODO: FIXME: implements it.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpNotFoundHandler::SrsGoHttpNotFoundHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpNotFoundHandler::~SrsGoHttpNotFoundHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpNotFoundHandler::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
|
{
|
||||||
|
return srs_go_http_error(w,
|
||||||
|
SRS_CONSTS_HTTP_NotFound, SRS_CONSTS_HTTP_NotFound_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpMuxEntry::SrsGoHttpMuxEntry()
|
||||||
|
{
|
||||||
|
explicit_match = false;
|
||||||
|
handler = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpMuxEntry::~SrsGoHttpMuxEntry()
|
||||||
|
{
|
||||||
|
srs_freep(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpServeMux::SrsGoHttpServeMux()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpServeMux::~SrsGoHttpServeMux()
|
||||||
|
{
|
||||||
|
std::map<std::string, SrsGoHttpMuxEntry*>::iterator it;
|
||||||
|
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||||
|
SrsGoHttpMuxEntry* entry = it->second;
|
||||||
|
srs_freep(entry);
|
||||||
|
}
|
||||||
|
entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpServeMux::initialize()
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
// TODO: FIXME: implements it.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpServeMux::handle(std::string pattern, ISrsGoHttpHandler* handler)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
srs_assert(handler);
|
||||||
|
|
||||||
|
if (pattern.empty()) {
|
||||||
|
ret = ERROR_HTTP_PATTERN_EMPTY;
|
||||||
|
srs_error("http: empty pattern. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.find(pattern) != entries.end()) {
|
||||||
|
SrsGoHttpMuxEntry* exists = entries[pattern];
|
||||||
|
if (exists->explicit_match) {
|
||||||
|
ret = ERROR_HTTP_PATTERN_DUPLICATED;
|
||||||
|
srs_error("http: multiple registrations for %s. ret=%d", pattern.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
SrsGoHttpMuxEntry* entry = new SrsGoHttpMuxEntry();
|
||||||
|
entry->explicit_match = true;
|
||||||
|
entry->handler = handler;
|
||||||
|
entry->pattern = pattern;
|
||||||
|
|
||||||
|
if (entries.find(pattern) != entries.end()) {
|
||||||
|
SrsGoHttpMuxEntry* exists = entries[pattern];
|
||||||
|
srs_freep(exists);
|
||||||
|
}
|
||||||
|
entries[pattern] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpful behavior:
|
||||||
|
// If pattern is /tree/, insert an implicit permanent redirect for /tree.
|
||||||
|
// It can be overridden by an explicit registration.
|
||||||
|
if (!pattern.empty() && pattern.at(pattern.length() - 1) == '/') {
|
||||||
|
std::string rpattern = pattern.substr(0, pattern.length() - 1);
|
||||||
|
SrsGoHttpMuxEntry* entry = NULL;
|
||||||
|
|
||||||
|
// free the exists not explicit entry
|
||||||
|
if (entries.find(rpattern) != entries.end()) {
|
||||||
|
SrsGoHttpMuxEntry* exists = entries[rpattern];
|
||||||
|
if (!exists->explicit_match) {
|
||||||
|
entry = exists;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create implicit redirect.
|
||||||
|
if (!entry || entry->explicit_match) {
|
||||||
|
srs_freep(entry);
|
||||||
|
|
||||||
|
entry = new SrsGoHttpMuxEntry();
|
||||||
|
entry->explicit_match = false;
|
||||||
|
entry->handler = new SrsGoHttpRedirectHandler(pattern, SRS_CONSTS_HTTP_MovedPermanently);
|
||||||
|
entry->pattern = pattern;
|
||||||
|
|
||||||
|
entries[rpattern] = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpServeMux::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
ISrsGoHttpHandler* h = NULL;
|
||||||
|
if ((ret = find_handler(r, &h)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("find handler failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_assert(h);
|
||||||
|
if ((ret = h->serve_http(w, r)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("handler serve http failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpServeMux::find_handler(SrsHttpMessage* r, ISrsGoHttpHandler** ph)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// TODO: FIXME: support the path . and ..
|
||||||
|
if (r->url().find("..") != std::string::npos) {
|
||||||
|
ret = ERROR_HTTP_URL_NOT_CLEAN;
|
||||||
|
srs_error("htt url not canonical, url=%s. ret=%d", r->url().c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = match(r, ph)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("http match handler failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ph == NULL) {
|
||||||
|
*ph = new SrsGoHttpNotFoundHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpServeMux::match(SrsHttpMessage* r, ISrsGoHttpHandler** ph)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
std::string path = r->path();
|
||||||
|
|
||||||
|
int nb_matched = 0;
|
||||||
|
ISrsGoHttpHandler* h = NULL;
|
||||||
|
|
||||||
|
std::map<std::string, SrsGoHttpMuxEntry*>::iterator it;
|
||||||
|
for (it = entries.begin(); it != entries.end(); ++it) {
|
||||||
|
std::string pattern = it->first;
|
||||||
|
SrsGoHttpMuxEntry* entry = it->second;
|
||||||
|
|
||||||
|
if (!path_match(pattern, path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!h || (int)pattern.length() > nb_matched) {
|
||||||
|
nb_matched = (int)pattern.length();
|
||||||
|
h = entry->handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*ph = h;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsGoHttpServeMux::path_match(string pattern, string path)
|
||||||
|
{
|
||||||
|
if (pattern.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = pattern.length();
|
||||||
|
|
||||||
|
// not endswith '/', exactly match.
|
||||||
|
if (pattern.at(n - 1) != '/') {
|
||||||
|
return pattern == path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// endswith '/', match any,
|
||||||
|
// for example, '/api/' match '/api/[N]'
|
||||||
|
if ((int)path.length() >= n) {
|
||||||
|
if (memcmp(pattern.data(), path.data(), n) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpResponseWriter::SrsGoHttpResponseWriter(SrsStSocket* io)
|
||||||
|
{
|
||||||
|
skt = io;
|
||||||
|
hdr = new SrsGoHttpHeader();
|
||||||
|
header_wrote = false;
|
||||||
|
status = SRS_CONSTS_HTTP_OK;
|
||||||
|
content_length = -1;
|
||||||
|
written = 0;
|
||||||
|
header_sent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpResponseWriter::~SrsGoHttpResponseWriter()
|
||||||
|
{
|
||||||
|
srs_freep(hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoHttpHeader* SrsGoHttpResponseWriter::header()
|
||||||
|
{
|
||||||
|
return hdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpResponseWriter::write(char* data, int size)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (!header_wrote) {
|
||||||
|
write_header(SRS_CONSTS_HTTP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
written += size;
|
||||||
|
if (content_length != -1 && written > content_length) {
|
||||||
|
ret = ERROR_HTTP_CONTENT_LENGTH;
|
||||||
|
srs_error("http: exceed content length. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = send_header(data, size)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("http: send header failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return skt->write((void*)data, size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsGoHttpResponseWriter::write_header(int code)
|
||||||
|
{
|
||||||
|
if (header_wrote) {
|
||||||
|
srs_warn("http: multiple write_header calls, code=%d", code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
header_wrote = true;
|
||||||
|
status = code;
|
||||||
|
|
||||||
|
// parse the content length from header.
|
||||||
|
content_length = hdr->content_length();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoHttpResponseWriter::send_header(char* data, int size)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (header_sent) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
header_sent = true;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
// status_line
|
||||||
|
ss << "HTTP/1.1 " << status << " "
|
||||||
|
<< srs_generate_status_text(status) << __SRS_CRLF;
|
||||||
|
|
||||||
|
// detect content type
|
||||||
|
if (srs_go_http_body_allowd(status)) {
|
||||||
|
if (hdr->content_type().empty()) {
|
||||||
|
hdr->set_content_type(srs_go_http_detect(data, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set server if not set.
|
||||||
|
if (hdr->get("Server").empty()) {
|
||||||
|
hdr->set("Server", RTMP_SIG_SRS_KEY"/"RTMP_SIG_SRS_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write headers
|
||||||
|
hdr->write(ss);
|
||||||
|
|
||||||
|
// header_eof
|
||||||
|
ss << __SRS_CRLF;
|
||||||
|
|
||||||
|
std::string buf = ss.str();
|
||||||
|
return skt->write((void*)buf.c_str(), buf.length(), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
SrsHttpHandlerMatch::SrsHttpHandlerMatch()
|
SrsHttpHandlerMatch::SrsHttpHandlerMatch()
|
||||||
{
|
{
|
||||||
handler = NULL;
|
handler = NULL;
|
||||||
|
@ -521,13 +1018,6 @@ int SrsHttpHandler::res_error(SrsStSocket* skt, SrsHttpMessage* req, int code, s
|
||||||
return res_flush(skt, ss);
|
return res_flush(skt, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
|
||||||
SrsHttpHandler* SrsHttpHandler::create_http_api()
|
|
||||||
{
|
|
||||||
return new SrsApiRoot();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_SERVER
|
#ifdef SRS_AUTO_HTTP_SERVER
|
||||||
SrsHttpHandler* SrsHttpHandler::create_http_stream()
|
SrsHttpHandler* SrsHttpHandler::create_http_stream()
|
||||||
{
|
{
|
||||||
|
@ -553,6 +1043,41 @@ SrsHttpMessage::~SrsHttpMessage()
|
||||||
srs_freep(_http_ts_send_buffer);
|
srs_freep(_http_ts_send_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsHttpMessage::initialize()
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// parse uri to schema/server:port/path?query
|
||||||
|
if ((ret = _uri->initialize(_url)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must format as key=value&...&keyN=valueN
|
||||||
|
std::string q = _uri->get_query();
|
||||||
|
size_t pos = string::npos;
|
||||||
|
while (!q.empty()) {
|
||||||
|
std::string k = q;
|
||||||
|
if ((pos = q.find("=")) != string::npos) {
|
||||||
|
k = q.substr(0, pos);
|
||||||
|
q = q.substr(pos + 1);
|
||||||
|
} else {
|
||||||
|
q = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string v = q;
|
||||||
|
if ((pos = q.find("&")) != string::npos) {
|
||||||
|
v = q.substr(0, pos);
|
||||||
|
q = q.substr(pos + 1);
|
||||||
|
} else {
|
||||||
|
q = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
_query[k] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
char* SrsHttpMessage::http_ts_send_buffer()
|
char* SrsHttpMessage::http_ts_send_buffer()
|
||||||
{
|
{
|
||||||
return _http_ts_send_buffer;
|
return _http_ts_send_buffer;
|
||||||
|
@ -565,24 +1090,6 @@ void SrsHttpMessage::reset()
|
||||||
_url = "";
|
_url = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpMessage::parse_uri()
|
|
||||||
{
|
|
||||||
// filter url according to HTTP specification.
|
|
||||||
|
|
||||||
// remove the duplicated slash.
|
|
||||||
std::string filtered_url = srs_string_replace(_url, "//", "/");
|
|
||||||
|
|
||||||
// remove the last / to match resource.
|
|
||||||
filtered_url = srs_string_trim_end(filtered_url, "/");
|
|
||||||
|
|
||||||
// if empty, use root.
|
|
||||||
if (filtered_url.empty()) {
|
|
||||||
filtered_url = "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
return _uri->initialize(filtered_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SrsHttpMessage::is_complete()
|
bool SrsHttpMessage::is_complete()
|
||||||
{
|
{
|
||||||
return _state == SrsHttpParseStateComplete;
|
return _state == SrsHttpParseStateComplete;
|
||||||
|
@ -671,11 +1178,6 @@ string SrsHttpMessage::path()
|
||||||
return _uri->get_path();
|
return _uri->get_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
string SrsHttpMessage::query()
|
|
||||||
{
|
|
||||||
return _uri->get_query();
|
|
||||||
}
|
|
||||||
|
|
||||||
string SrsHttpMessage::body()
|
string SrsHttpMessage::body()
|
||||||
{
|
{
|
||||||
std::string b;
|
std::string b;
|
||||||
|
@ -745,21 +1247,10 @@ void SrsHttpMessage::append_body(const char* body, int length)
|
||||||
|
|
||||||
string SrsHttpMessage::query_get(string key)
|
string SrsHttpMessage::query_get(string key)
|
||||||
{
|
{
|
||||||
std::string q = query();
|
std::string v;
|
||||||
size_t pos = std::string::npos;
|
|
||||||
|
|
||||||
// must format as key=value&...&keyN=valueN
|
if (_query.find(key) != _query.end()) {
|
||||||
if ((pos = key.find("=")) != key.length() - 1) {
|
v = _query[key];
|
||||||
key = key + "=";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pos = q.find(key)) == std::string::npos) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string v = q.substr(pos + key.length());
|
|
||||||
if ((pos = v.find("&")) != std::string::npos) {
|
|
||||||
v = v.substr(0, pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
@ -860,6 +1351,13 @@ int SrsHttpParser::parse_message(SrsStSocket* skt, SrsHttpMessage** ppmsg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initalize http msg, parse url.
|
||||||
|
if ((ret = msg->initialize()) != ERROR_SUCCESS) {
|
||||||
|
srs_error("initialize http msg failed. ret=%d", ret);
|
||||||
|
srs_freep(msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// parse ok, return the msg.
|
// parse ok, return the msg.
|
||||||
*ppmsg = msg;
|
*ppmsg = msg;
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
|
|
|
@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_PARSER
|
#ifdef SRS_AUTO_HTTP_PARSER
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -45,6 +46,7 @@ class SrsStSocket;
|
||||||
class SrsHttpUri;
|
class SrsHttpUri;
|
||||||
class SrsHttpMessage;
|
class SrsHttpMessage;
|
||||||
class SrsHttpHandler;
|
class SrsHttpHandler;
|
||||||
|
class ISrsGoHttpResponseWriter;
|
||||||
|
|
||||||
// http specification
|
// http specification
|
||||||
// CR = <US-ASCII CR, carriage return (13)>
|
// CR = <US-ASCII CR, carriage return (13)>
|
||||||
|
@ -65,6 +67,9 @@ class SrsHttpHandler;
|
||||||
// @see SrsHttpMessage._http_ts_send_buffer
|
// @see SrsHttpMessage._http_ts_send_buffer
|
||||||
#define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
|
#define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
|
||||||
|
|
||||||
|
// helper function: response in json format.
|
||||||
|
extern int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, std::string data);
|
||||||
|
|
||||||
// compare the path.
|
// compare the path.
|
||||||
// full compare, extractly match.
|
// full compare, extractly match.
|
||||||
// used for api match.
|
// used for api match.
|
||||||
|
@ -81,6 +86,214 @@ enum SrsHttpParseState {
|
||||||
SrsHttpParseStateComplete
|
SrsHttpParseStateComplete
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A Header represents the key-value pairs in an HTTP header.
|
||||||
|
class SrsGoHttpHeader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::string> headers;
|
||||||
|
public:
|
||||||
|
SrsGoHttpHeader();
|
||||||
|
virtual ~SrsGoHttpHeader();
|
||||||
|
public:
|
||||||
|
// Add adds the key, value pair to the header.
|
||||||
|
// It appends to any existing values associated with key.
|
||||||
|
virtual void set(std::string key, std::string value);
|
||||||
|
// Get gets the first value associated with the given key.
|
||||||
|
// If there are no values associated with the key, Get returns "".
|
||||||
|
// To access multiple values of a key, access the map directly
|
||||||
|
// with CanonicalHeaderKey.
|
||||||
|
virtual std::string get(std::string key);
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* get the content length. -1 if not set.
|
||||||
|
*/
|
||||||
|
virtual int64_t content_length();
|
||||||
|
/**
|
||||||
|
* set the content length by header "Content-Length"
|
||||||
|
*/
|
||||||
|
virtual void set_content_length(int64_t size);
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* get the content type. empty string if not set.
|
||||||
|
*/
|
||||||
|
virtual std::string content_type();
|
||||||
|
/**
|
||||||
|
* set the content type by header "Content-Type"
|
||||||
|
*/
|
||||||
|
virtual void set_content_type(std::string ct);
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* write all headers to string stream.
|
||||||
|
*/
|
||||||
|
virtual void write(std::stringstream& ss);
|
||||||
|
};
|
||||||
|
|
||||||
|
// A ResponseWriter interface is used by an HTTP handler to
|
||||||
|
// construct an HTTP response.
|
||||||
|
class ISrsGoHttpResponseWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ISrsGoHttpResponseWriter();
|
||||||
|
virtual ~ISrsGoHttpResponseWriter();
|
||||||
|
public:
|
||||||
|
// Header returns the header map that will be sent by WriteHeader.
|
||||||
|
// Changing the header after a call to WriteHeader (or Write) has
|
||||||
|
// no effect.
|
||||||
|
virtual SrsGoHttpHeader* header() = 0;
|
||||||
|
|
||||||
|
// Write writes the data to the connection as part of an HTTP reply.
|
||||||
|
// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
|
||||||
|
// before writing the data. If the Header does not contain a
|
||||||
|
// Content-Type line, Write adds a Content-Type set to the result of passing
|
||||||
|
// the initial 512 bytes of written data to DetectContentType.
|
||||||
|
virtual int write(char* data, int size) = 0;
|
||||||
|
|
||||||
|
// WriteHeader sends an HTTP response header with status code.
|
||||||
|
// If WriteHeader is not called explicitly, the first call to Write
|
||||||
|
// will trigger an implicit WriteHeader(http.StatusOK).
|
||||||
|
// Thus explicit calls to WriteHeader are mainly used to
|
||||||
|
// send error codes.
|
||||||
|
virtual void write_header(int code) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Objects implementing the Handler interface can be
|
||||||
|
// registered to serve a particular path or subtree
|
||||||
|
// in the HTTP server.
|
||||||
|
//
|
||||||
|
// ServeHTTP should write reply headers and data to the ResponseWriter
|
||||||
|
// and then return. Returning signals that the request is finished
|
||||||
|
// and that the HTTP server can move on to the next request on
|
||||||
|
// the connection.
|
||||||
|
class ISrsGoHttpHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ISrsGoHttpHandler();
|
||||||
|
virtual ~ISrsGoHttpHandler();
|
||||||
|
public:
|
||||||
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Redirect to a fixed URL
|
||||||
|
class SrsGoHttpRedirectHandler : public ISrsGoHttpHandler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string url;
|
||||||
|
int code;
|
||||||
|
public:
|
||||||
|
SrsGoHttpRedirectHandler(std::string u, int c);
|
||||||
|
virtual ~SrsGoHttpRedirectHandler();
|
||||||
|
public:
|
||||||
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
|
};
|
||||||
|
|
||||||
|
// NotFound replies to the request with an HTTP 404 not found error.
|
||||||
|
class SrsGoHttpNotFoundHandler : public ISrsGoHttpHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsGoHttpNotFoundHandler();
|
||||||
|
virtual ~SrsGoHttpNotFoundHandler();
|
||||||
|
public:
|
||||||
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
|
};
|
||||||
|
|
||||||
|
// the mux entry for server mux.
|
||||||
|
class SrsGoHttpMuxEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool explicit_match;
|
||||||
|
ISrsGoHttpHandler* handler;
|
||||||
|
std::string pattern;
|
||||||
|
public:
|
||||||
|
SrsGoHttpMuxEntry();
|
||||||
|
virtual ~SrsGoHttpMuxEntry();
|
||||||
|
};
|
||||||
|
|
||||||
|
// ServeMux is an HTTP request multiplexer.
|
||||||
|
// It matches the URL of each incoming request against a list of registered
|
||||||
|
// patterns and calls the handler for the pattern that
|
||||||
|
// most closely matches the URL.
|
||||||
|
//
|
||||||
|
// Patterns name fixed, rooted paths, like "/favicon.ico",
|
||||||
|
// or rooted subtrees, like "/images/" (note the trailing slash).
|
||||||
|
// Longer patterns take precedence over shorter ones, so that
|
||||||
|
// if there are handlers registered for both "/images/"
|
||||||
|
// and "/images/thumbnails/", the latter handler will be
|
||||||
|
// called for paths beginning "/images/thumbnails/" and the
|
||||||
|
// former will receive requests for any other paths in the
|
||||||
|
// "/images/" subtree.
|
||||||
|
//
|
||||||
|
// Note that since a pattern ending in a slash names a rooted subtree,
|
||||||
|
// the pattern "/" matches all paths not matched by other registered
|
||||||
|
// patterns, not just the URL with Path == "/".
|
||||||
|
//
|
||||||
|
// Patterns may optionally begin with a host name, restricting matches to
|
||||||
|
// URLs on that host only. Host-specific patterns take precedence over
|
||||||
|
// general patterns, so that a handler might register for the two patterns
|
||||||
|
// "/codesearch" and "codesearch.google.com/" without also taking over
|
||||||
|
// requests for "http://www.google.com/".
|
||||||
|
//
|
||||||
|
// ServeMux also takes care of sanitizing the URL request path,
|
||||||
|
// redirecting any request containing . or .. elements to an
|
||||||
|
// equivalent .- and ..-free URL.
|
||||||
|
class SrsGoHttpServeMux
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::map<std::string, SrsGoHttpMuxEntry*> entries;
|
||||||
|
public:
|
||||||
|
SrsGoHttpServeMux();
|
||||||
|
virtual ~SrsGoHttpServeMux();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* initialize the http serve mux.
|
||||||
|
*/
|
||||||
|
virtual int initialize();
|
||||||
|
public:
|
||||||
|
// Handle registers the handler for the given pattern.
|
||||||
|
// If a handler already exists for pattern, Handle panics.
|
||||||
|
virtual int handle(std::string pattern, ISrsGoHttpHandler* handler);
|
||||||
|
// interface ISrsGoHttpHandler
|
||||||
|
public:
|
||||||
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
|
private:
|
||||||
|
virtual int find_handler(SrsHttpMessage* r, ISrsGoHttpHandler** ph);
|
||||||
|
virtual int match(SrsHttpMessage* r, ISrsGoHttpHandler** ph);
|
||||||
|
virtual bool path_match(std::string pattern, std::string path);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* response writer use st socket
|
||||||
|
*/
|
||||||
|
class SrsGoHttpResponseWriter : public ISrsGoHttpResponseWriter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SrsStSocket* skt;
|
||||||
|
SrsGoHttpHeader* hdr;
|
||||||
|
private:
|
||||||
|
// reply header has been (logically) written
|
||||||
|
bool header_wrote;
|
||||||
|
// status code passed to WriteHeader
|
||||||
|
int status;
|
||||||
|
private:
|
||||||
|
// explicitly-declared Content-Length; or -1
|
||||||
|
int64_t content_length;
|
||||||
|
// number of bytes written in body
|
||||||
|
int64_t written;
|
||||||
|
private:
|
||||||
|
// wroteHeader tells whether the header's been written to "the
|
||||||
|
// wire" (or rather: w.conn.buf). this is unlike
|
||||||
|
// (*response).wroteHeader, which tells only whether it was
|
||||||
|
// logically written.
|
||||||
|
bool header_sent;
|
||||||
|
public:
|
||||||
|
SrsGoHttpResponseWriter(SrsStSocket* io);
|
||||||
|
virtual ~SrsGoHttpResponseWriter();
|
||||||
|
public:
|
||||||
|
virtual SrsGoHttpHeader* header();
|
||||||
|
virtual int write(char* data, int size);
|
||||||
|
virtual void write_header(int code);
|
||||||
|
virtual int send_header(char* data, int size);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the matched handler info.
|
* the matched handler info.
|
||||||
*/
|
*/
|
||||||
|
@ -182,12 +395,6 @@ public:
|
||||||
virtual int res_error(SrsStSocket* skt, SrsHttpMessage* req, int code, std::string reason_phrase, std::string body);
|
virtual int res_error(SrsStSocket* skt, SrsHttpMessage* req, int code, std::string reason_phrase, std::string body);
|
||||||
// object creator
|
// object creator
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* create http api resource handler.
|
|
||||||
*/
|
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
|
||||||
static SrsHttpHandler* create_http_api();
|
|
||||||
#endif
|
|
||||||
/**
|
/**
|
||||||
* create http stream resource handler.
|
* create http stream resource handler.
|
||||||
*/
|
*/
|
||||||
|
@ -196,6 +403,12 @@ public:
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A Request represents an HTTP request received by a server
|
||||||
|
// or to be sent by a client.
|
||||||
|
//
|
||||||
|
// The field semantics differ slightly between client and server
|
||||||
|
// usage. In addition to the notes on the fields below, see the
|
||||||
|
// documentation for Request.Write and RoundTripper.
|
||||||
/**
|
/**
|
||||||
* the http message, request or response.
|
* the http message, request or response.
|
||||||
*/
|
*/
|
||||||
|
@ -239,13 +452,16 @@ private:
|
||||||
// http headers
|
// http headers
|
||||||
typedef std::pair<std::string, std::string> SrsHttpHeaderField;
|
typedef std::pair<std::string, std::string> SrsHttpHeaderField;
|
||||||
std::vector<SrsHttpHeaderField> headers;
|
std::vector<SrsHttpHeaderField> headers;
|
||||||
|
// the query map
|
||||||
|
std::map<std::string, std::string> _query;
|
||||||
public:
|
public:
|
||||||
SrsHttpMessage();
|
SrsHttpMessage();
|
||||||
virtual ~SrsHttpMessage();
|
virtual ~SrsHttpMessage();
|
||||||
|
public:
|
||||||
|
virtual int initialize();
|
||||||
public:
|
public:
|
||||||
virtual char* http_ts_send_buffer();
|
virtual char* http_ts_send_buffer();
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
virtual int parse_uri();
|
|
||||||
public:
|
public:
|
||||||
virtual bool is_complete();
|
virtual bool is_complete();
|
||||||
virtual u_int8_t method();
|
virtual u_int8_t method();
|
||||||
|
@ -260,7 +476,7 @@ public:
|
||||||
virtual std::string url();
|
virtual std::string url();
|
||||||
virtual std::string host();
|
virtual std::string host();
|
||||||
virtual std::string path();
|
virtual std::string path();
|
||||||
virtual std::string query();
|
public:
|
||||||
virtual std::string body();
|
virtual std::string body();
|
||||||
virtual char* body_raw();
|
virtual char* body_raw();
|
||||||
virtual int64_t body_size();
|
virtual int64_t body_size();
|
||||||
|
@ -273,14 +489,12 @@ public:
|
||||||
virtual void set_match(SrsHttpHandlerMatch* match);
|
virtual void set_match(SrsHttpHandlerMatch* match);
|
||||||
virtual void set_requires_crossdomain(bool requires_crossdomain);
|
virtual void set_requires_crossdomain(bool requires_crossdomain);
|
||||||
virtual void append_body(const char* body, int length);
|
virtual void append_body(const char* body, int length);
|
||||||
public:
|
|
||||||
/**
|
/**
|
||||||
* get the param in query string,
|
* get the param in query string,
|
||||||
* for instance, query is "start=100&end=200",
|
* for instance, query is "start=100&end=200",
|
||||||
* then query_get("start") is "100", and query_get("end") is "200"
|
* then query_get("start") is "100", and query_get("end") is "200"
|
||||||
*/
|
*/
|
||||||
virtual std::string query_get(std::string key);
|
virtual std::string query_get(std::string key);
|
||||||
public:
|
|
||||||
virtual int request_header_count();
|
virtual int request_header_count();
|
||||||
virtual std::string request_header_key_at(int index);
|
virtual std::string request_header_key_at(int index);
|
||||||
virtual std::string request_header_value_at(int index);
|
virtual std::string request_header_value_at(int index);
|
||||||
|
|
|
@ -38,41 +38,15 @@ using namespace std;
|
||||||
#include <srs_app_statistic.hpp>
|
#include <srs_app_statistic.hpp>
|
||||||
#include <srs_protocol_rtmp.hpp>
|
#include <srs_protocol_rtmp.hpp>
|
||||||
|
|
||||||
SrsApiRoot::SrsApiRoot()
|
SrsGoApiRoot::SrsGoApiRoot()
|
||||||
{
|
|
||||||
handlers.push_back(new SrsApiApi());
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsApiRoot::~SrsApiRoot()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiRoot::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase)
|
SrsGoApiRoot::~SrsGoApiRoot()
|
||||||
{
|
{
|
||||||
if (!SrsHttpHandler::is_handler_valid(req, status_code, reason_phrase)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->match()->matched_url.length() != 1) {
|
|
||||||
status_code = SRS_CONSTS_HTTP_NotFound;
|
|
||||||
reason_phrase = SRS_CONSTS_HTTP_NotFound_str;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiRoot::can_handle(const char* path, int /*length*/, const char** pchild)
|
int SrsGoApiRoot::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
// reset the child path to path,
|
|
||||||
// for child to reparse the path.
|
|
||||||
*pchild = path;
|
|
||||||
|
|
||||||
// only compare the first char.
|
|
||||||
return srs_path_equals("/", path, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiRoot::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -83,24 +57,18 @@ int SrsApiRoot::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiApi::SrsApiApi()
|
SrsGoApiApi::SrsGoApiApi()
|
||||||
{
|
|
||||||
handlers.push_back(new SrsApiV1());
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsApiApi::~SrsApiApi()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiApi::can_handle(const char* path, int length, const char** /*pchild*/)
|
SrsGoApiApi::~SrsGoApiApi()
|
||||||
{
|
{
|
||||||
return srs_path_equals("/api", path, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsApiApi::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
int SrsGoApiApi::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -111,33 +79,18 @@ int SrsApiApi::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiV1::SrsApiV1()
|
SrsGoApiV1::SrsGoApiV1()
|
||||||
{
|
|
||||||
handlers.push_back(new SrsApiVersion());
|
|
||||||
handlers.push_back(new SrsApiSummaries());
|
|
||||||
handlers.push_back(new SrsApiRusages());
|
|
||||||
handlers.push_back(new SrsApiSelfProcStats());
|
|
||||||
handlers.push_back(new SrsApiSystemProcStats());
|
|
||||||
handlers.push_back(new SrsApiMemInfos());
|
|
||||||
handlers.push_back(new SrsApiAuthors());
|
|
||||||
handlers.push_back(new SrsApiRequests());
|
|
||||||
handlers.push_back(new SrsApiVhosts());
|
|
||||||
handlers.push_back(new SrsApiStreams());
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsApiV1::~SrsApiV1()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiV1::can_handle(const char* path, int length, const char** /*pchild*/)
|
SrsGoApiV1::~SrsGoApiV1()
|
||||||
{
|
{
|
||||||
return srs_path_equals("/v1", path, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsApiV1::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
int SrsGoApiV1::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -157,87 +110,18 @@ int SrsApiV1::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiRequests::SrsApiRequests()
|
SrsGoApiVersion::SrsGoApiVersion()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiRequests::~SrsApiRequests()
|
SrsGoApiVersion::~SrsGoApiVersion()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiRequests::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiVersion::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
return srs_path_equals("/requests", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiRequests::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
|
|
||||||
ss << __SRS_JOBJECT_START
|
|
||||||
<< __SRS_JFIELD_ERROR(ERROR_SUCCESS) << __SRS_JFIELD_CONT
|
|
||||||
<< __SRS_JFIELD_ORG("data", __SRS_JOBJECT_START)
|
|
||||||
<< __SRS_JFIELD_STR("uri", req->uri()) << __SRS_JFIELD_CONT
|
|
||||||
<< __SRS_JFIELD_STR("path", req->path()) << __SRS_JFIELD_CONT;
|
|
||||||
|
|
||||||
// method
|
|
||||||
if (req->is_http_get()) {
|
|
||||||
ss << __SRS_JFIELD_STR("METHOD", "GET");
|
|
||||||
} else if (req->is_http_post()) {
|
|
||||||
ss << __SRS_JFIELD_STR("METHOD", "POST");
|
|
||||||
} else if (req->is_http_put()) {
|
|
||||||
ss << __SRS_JFIELD_STR("METHOD", "PUT");
|
|
||||||
} else if (req->is_http_delete()) {
|
|
||||||
ss << __SRS_JFIELD_STR("METHOD", "DELETE");
|
|
||||||
} else {
|
|
||||||
ss << __SRS_JFIELD_ORG("METHOD", req->method());
|
|
||||||
}
|
|
||||||
ss << __SRS_JFIELD_CONT;
|
|
||||||
|
|
||||||
// request headers
|
|
||||||
ss << __SRS_JFIELD_NAME("headers") << __SRS_JOBJECT_START;
|
|
||||||
for (int i = 0; i < req->request_header_count(); i++) {
|
|
||||||
std::string key = req->request_header_key_at(i);
|
|
||||||
std::string value = req->request_header_value_at(i);
|
|
||||||
if ( i < req->request_header_count() - 1) {
|
|
||||||
ss << __SRS_JFIELD_STR(key, value) << __SRS_JFIELD_CONT;
|
|
||||||
} else {
|
|
||||||
ss << __SRS_JFIELD_STR(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ss << __SRS_JOBJECT_END << __SRS_JFIELD_CONT;
|
|
||||||
|
|
||||||
// server informations
|
|
||||||
ss << __SRS_JFIELD_NAME("server") << __SRS_JOBJECT_START
|
|
||||||
<< __SRS_JFIELD_STR("sigature", RTMP_SIG_SRS_KEY) << __SRS_JFIELD_CONT
|
|
||||||
<< __SRS_JFIELD_STR("name", RTMP_SIG_SRS_NAME) << __SRS_JFIELD_CONT
|
|
||||||
<< __SRS_JFIELD_STR("version", RTMP_SIG_SRS_VERSION) << __SRS_JFIELD_CONT
|
|
||||||
<< __SRS_JFIELD_STR("link", RTMP_SIG_SRS_URL) << __SRS_JFIELD_CONT
|
|
||||||
<< __SRS_JFIELD_ORG("time", srs_get_system_time_ms())
|
|
||||||
<< __SRS_JOBJECT_END
|
|
||||||
<< __SRS_JOBJECT_END
|
|
||||||
<< __SRS_JOBJECT_END;
|
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsApiVersion::SrsApiVersion()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsApiVersion::~SrsApiVersion()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SrsApiVersion::can_handle(const char* path, int length, const char** /*pchild*/)
|
|
||||||
{
|
|
||||||
return srs_path_equals("/versions", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiVersion::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -251,43 +135,33 @@ int SrsApiVersion::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiSummaries::SrsApiSummaries()
|
SrsGoApiSummaries::SrsGoApiSummaries()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiSummaries::~SrsApiSummaries()
|
SrsGoApiSummaries::~SrsGoApiSummaries()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiSummaries::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiSummaries::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
return srs_path_equals("/summaries", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiSummaries::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
srs_api_dump_summaries(ss);
|
srs_api_dump_summaries(ss);
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiRusages::SrsApiRusages()
|
SrsGoApiRusages::SrsGoApiRusages()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiRusages::~SrsApiRusages()
|
SrsGoApiRusages::~SrsGoApiRusages()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiRusages::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiRusages::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* req)
|
||||||
{
|
|
||||||
return srs_path_equals("/rusages", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiRusages::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -317,23 +191,18 @@ int SrsApiRusages::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiSelfProcStats::SrsApiSelfProcStats()
|
SrsGoApiSelfProcStats::SrsGoApiSelfProcStats()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiSelfProcStats::~SrsApiSelfProcStats()
|
SrsGoApiSelfProcStats::~SrsGoApiSelfProcStats()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiSelfProcStats::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiSelfProcStats::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
return srs_path_equals("/self_proc_stats", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiSelfProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -392,23 +261,18 @@ int SrsApiSelfProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* re
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiSystemProcStats::SrsApiSystemProcStats()
|
SrsGoApiSystemProcStats::SrsGoApiSystemProcStats()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiSystemProcStats::~SrsApiSystemProcStats()
|
SrsGoApiSystemProcStats::~SrsGoApiSystemProcStats()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiSystemProcStats::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiSystemProcStats::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
return srs_path_equals("/system_proc_stats", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiSystemProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -432,23 +296,18 @@ int SrsApiSystemProcStats::do_process_request(SrsStSocket* skt, SrsHttpMessage*
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiMemInfos::SrsApiMemInfos()
|
SrsGoApiMemInfos::SrsGoApiMemInfos()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiMemInfos::~SrsApiMemInfos()
|
SrsGoApiMemInfos::~SrsGoApiMemInfos()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiMemInfos::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiMemInfos::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
return srs_path_equals("/meminfos", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiMemInfos::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -473,23 +332,18 @@ int SrsApiMemInfos::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiAuthors::SrsApiAuthors()
|
SrsGoApiAuthors::SrsGoApiAuthors()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiAuthors::~SrsApiAuthors()
|
SrsGoApiAuthors::~SrsGoApiAuthors()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiAuthors::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiAuthors::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
return srs_path_equals("/authors", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiAuthors::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
@ -503,24 +357,82 @@ int SrsApiAuthors::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JOBJECT_END
|
<< __SRS_JOBJECT_END
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiVhosts::SrsApiVhosts()
|
SrsGoApiRequests::SrsGoApiRequests()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiVhosts::~SrsApiVhosts()
|
SrsGoApiRequests::~SrsGoApiRequests()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiVhosts::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiRequests::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
{
|
||||||
return srs_path_equals("/vhosts", path, length);
|
SrsHttpMessage* req = r;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << __SRS_JOBJECT_START
|
||||||
|
<< __SRS_JFIELD_ERROR(ERROR_SUCCESS) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_ORG("data", __SRS_JOBJECT_START)
|
||||||
|
<< __SRS_JFIELD_STR("uri", req->uri()) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_STR("path", req->path()) << __SRS_JFIELD_CONT;
|
||||||
|
|
||||||
|
// method
|
||||||
|
if (req->is_http_get()) {
|
||||||
|
ss << __SRS_JFIELD_STR("METHOD", "GET");
|
||||||
|
} else if (req->is_http_post()) {
|
||||||
|
ss << __SRS_JFIELD_STR("METHOD", "POST");
|
||||||
|
} else if (req->is_http_put()) {
|
||||||
|
ss << __SRS_JFIELD_STR("METHOD", "PUT");
|
||||||
|
} else if (req->is_http_delete()) {
|
||||||
|
ss << __SRS_JFIELD_STR("METHOD", "DELETE");
|
||||||
|
} else {
|
||||||
|
ss << __SRS_JFIELD_ORG("METHOD", req->method());
|
||||||
|
}
|
||||||
|
ss << __SRS_JFIELD_CONT;
|
||||||
|
|
||||||
|
// request headers
|
||||||
|
ss << __SRS_JFIELD_NAME("headers") << __SRS_JOBJECT_START;
|
||||||
|
for (int i = 0; i < req->request_header_count(); i++) {
|
||||||
|
std::string key = req->request_header_key_at(i);
|
||||||
|
std::string value = req->request_header_value_at(i);
|
||||||
|
if ( i < req->request_header_count() - 1) {
|
||||||
|
ss << __SRS_JFIELD_STR(key, value) << __SRS_JFIELD_CONT;
|
||||||
|
} else {
|
||||||
|
ss << __SRS_JFIELD_STR(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss << __SRS_JOBJECT_END << __SRS_JFIELD_CONT;
|
||||||
|
|
||||||
|
// server informations
|
||||||
|
ss << __SRS_JFIELD_NAME("server") << __SRS_JOBJECT_START
|
||||||
|
<< __SRS_JFIELD_STR("sigature", RTMP_SIG_SRS_KEY) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_STR("name", RTMP_SIG_SRS_NAME) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_STR("version", RTMP_SIG_SRS_VERSION) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_STR("link", RTMP_SIG_SRS_URL) << __SRS_JFIELD_CONT
|
||||||
|
<< __SRS_JFIELD_ORG("time", srs_get_system_time_ms())
|
||||||
|
<< __SRS_JOBJECT_END
|
||||||
|
<< __SRS_JOBJECT_END
|
||||||
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsApiVhosts::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
SrsGoApiVhosts::SrsGoApiVhosts()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsGoApiVhosts::~SrsGoApiVhosts()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsGoApiVhosts::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
|
{
|
||||||
|
SrsHttpMessage* req = r;
|
||||||
|
|
||||||
std::stringstream data;
|
std::stringstream data;
|
||||||
SrsStatistic* stat = SrsStatistic::instance();
|
SrsStatistic* stat = SrsStatistic::instance();
|
||||||
int ret = stat->dumps_vhosts(data);
|
int ret = stat->dumps_vhosts(data);
|
||||||
|
@ -533,23 +445,18 @@ int SrsApiVhosts::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JFIELD_ORG("vhosts", data.str())
|
<< __SRS_JFIELD_ORG("vhosts", data.str())
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiStreams::SrsApiStreams()
|
SrsGoApiStreams::SrsGoApiStreams()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiStreams::~SrsApiStreams()
|
SrsGoApiStreams::~SrsGoApiStreams()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsApiStreams::can_handle(const char* path, int length, const char** /*pchild*/)
|
int SrsGoApiStreams::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
|
||||||
return srs_path_equals("/streams", path, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsApiStreams::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|
||||||
{
|
{
|
||||||
std::stringstream data;
|
std::stringstream data;
|
||||||
SrsStatistic* stat = SrsStatistic::instance();
|
SrsStatistic* stat = SrsStatistic::instance();
|
||||||
|
@ -563,15 +470,14 @@ int SrsApiStreams::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
<< __SRS_JFIELD_ORG("streams", data.str())
|
<< __SRS_JFIELD_ORG("streams", data.str())
|
||||||
<< __SRS_JOBJECT_END;
|
<< __SRS_JOBJECT_END;
|
||||||
|
|
||||||
return res_json(skt, req, ss.str());
|
return srs_go_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
|
SrsHttpApi::SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsGoHttpServeMux* m)
|
||||||
: SrsConnection(srs_server, client_stfd)
|
: SrsConnection(svr, fd)
|
||||||
{
|
{
|
||||||
|
mux = m;
|
||||||
parser = new SrsHttpParser();
|
parser = new SrsHttpParser();
|
||||||
handler = _handler;
|
|
||||||
requires_crossdomain = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHttpApi::~SrsHttpApi()
|
SrsHttpApi::~SrsHttpApi()
|
||||||
|
@ -628,7 +534,8 @@ int SrsHttpApi::do_cycle()
|
||||||
SrsAutoFree(SrsHttpMessage, req);
|
SrsAutoFree(SrsHttpMessage, req);
|
||||||
|
|
||||||
// ok, handle http request.
|
// ok, handle http request.
|
||||||
if ((ret = process_request(&skt, req)) != ERROR_SUCCESS) {
|
SrsGoHttpResponseWriter writer(&skt);
|
||||||
|
if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -636,46 +543,21 @@ int SrsHttpApi::do_cycle()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpApi::process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
int SrsHttpApi::process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// parse uri to schema/server:port/path?query
|
|
||||||
if ((ret = req->parse_uri()) != ERROR_SUCCESS) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
srs_trace("HTTP %s %s, content-length=%"PRId64"",
|
srs_trace("HTTP %s %s, content-length=%"PRId64"",
|
||||||
req->method_str().c_str(), req->url().c_str(), req->content_length());
|
r->method_str().c_str(), r->url().c_str(), r->content_length());
|
||||||
|
|
||||||
// TODO: maybe need to parse the url.
|
// use default server mux to serve http request.
|
||||||
std::string url = req->path();
|
if ((ret = mux->serve_http(w, r)) != ERROR_SUCCESS) {
|
||||||
|
if (!srs_is_client_gracefully_close(ret)) {
|
||||||
SrsHttpHandlerMatch* p = NULL;
|
srs_error("serve http msg failed. ret=%d", ret);
|
||||||
if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) {
|
|
||||||
srs_warn("failed to find the best match handler for url. ret=%d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if success, p and pstart should be valid.
|
|
||||||
srs_assert(p);
|
|
||||||
srs_assert(p->handler);
|
|
||||||
srs_assert(p->matched_url.length() <= url.length());
|
|
||||||
srs_info("best match handler, matched_url=%s", p->matched_url.c_str());
|
|
||||||
|
|
||||||
req->set_match(p);
|
|
||||||
req->set_requires_crossdomain(requires_crossdomain);
|
|
||||||
|
|
||||||
// use handler to process request.
|
|
||||||
if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) {
|
|
||||||
srs_warn("handler failed to process http request. ret=%d", ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->requires_crossdomain()) {
|
|
||||||
requires_crossdomain = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,158 +42,130 @@ class SrsHttpHandler;
|
||||||
#include <srs_app_http.hpp>
|
#include <srs_app_http.hpp>
|
||||||
|
|
||||||
// for http root.
|
// for http root.
|
||||||
class SrsApiRoot : public SrsHttpHandler
|
class SrsGoApiRoot : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiRoot();
|
SrsGoApiRoot();
|
||||||
virtual ~SrsApiRoot();
|
virtual ~SrsGoApiRoot();
|
||||||
public:
|
public:
|
||||||
virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiApi : public SrsHttpHandler
|
class SrsGoApiApi : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiApi();
|
SrsGoApiApi();
|
||||||
virtual ~SrsApiApi();
|
virtual ~SrsGoApiApi();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiV1 : public SrsHttpHandler
|
class SrsGoApiV1 : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiV1();
|
SrsGoApiV1();
|
||||||
virtual ~SrsApiV1();
|
virtual ~SrsGoApiV1();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiRequests : public SrsHttpHandler
|
class SrsGoApiVersion : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiRequests();
|
SrsGoApiVersion();
|
||||||
virtual ~SrsApiRequests();
|
virtual ~SrsGoApiVersion();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiVersion : public SrsHttpHandler
|
class SrsGoApiSummaries : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiVersion();
|
SrsGoApiSummaries();
|
||||||
virtual ~SrsApiVersion();
|
virtual ~SrsGoApiSummaries();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiSummaries : public SrsHttpHandler
|
class SrsGoApiRusages : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiSummaries();
|
SrsGoApiRusages();
|
||||||
virtual ~SrsApiSummaries();
|
virtual ~SrsGoApiRusages();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiRusages : public SrsHttpHandler
|
class SrsGoApiSelfProcStats : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiRusages();
|
SrsGoApiSelfProcStats();
|
||||||
virtual ~SrsApiRusages();
|
virtual ~SrsGoApiSelfProcStats();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiSelfProcStats : public SrsHttpHandler
|
class SrsGoApiSystemProcStats : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiSelfProcStats();
|
SrsGoApiSystemProcStats();
|
||||||
virtual ~SrsApiSelfProcStats();
|
virtual ~SrsGoApiSystemProcStats();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiSystemProcStats : public SrsHttpHandler
|
class SrsGoApiMemInfos : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiSystemProcStats();
|
SrsGoApiMemInfos();
|
||||||
virtual ~SrsApiSystemProcStats();
|
virtual ~SrsGoApiMemInfos();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiMemInfos : public SrsHttpHandler
|
class SrsGoApiAuthors : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiMemInfos();
|
SrsGoApiAuthors();
|
||||||
virtual ~SrsApiMemInfos();
|
virtual ~SrsGoApiAuthors();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiAuthors : public SrsHttpHandler
|
class SrsGoApiRequests : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiAuthors();
|
SrsGoApiRequests();
|
||||||
virtual ~SrsApiAuthors();
|
virtual ~SrsGoApiRequests();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiVhosts : public SrsHttpHandler
|
class SrsGoApiVhosts : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiVhosts();
|
SrsGoApiVhosts();
|
||||||
virtual ~SrsApiVhosts();
|
virtual ~SrsGoApiVhosts();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsApiStreams : public SrsHttpHandler
|
class SrsGoApiStreams : public ISrsGoHttpHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsApiStreams();
|
SrsGoApiStreams();
|
||||||
virtual ~SrsApiStreams();
|
virtual ~SrsGoApiStreams();
|
||||||
public:
|
public:
|
||||||
virtual bool can_handle(const char* path, int length, const char** pchild);
|
virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
protected:
|
|
||||||
virtual int do_process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsHttpApi : public SrsConnection
|
class SrsHttpApi : public SrsConnection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsHttpParser* parser;
|
SrsHttpParser* parser;
|
||||||
SrsHttpHandler* handler;
|
SrsGoHttpServeMux* mux;
|
||||||
bool requires_crossdomain;
|
|
||||||
public:
|
public:
|
||||||
SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler);
|
SrsHttpApi(SrsServer* svr, st_netfd_t fd, SrsGoHttpServeMux* m);
|
||||||
virtual ~SrsHttpApi();
|
virtual ~SrsHttpApi();
|
||||||
public:
|
public:
|
||||||
virtual void kbps_resample();
|
virtual void kbps_resample();
|
||||||
|
@ -204,7 +176,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual int do_cycle();
|
virtual int do_cycle();
|
||||||
private:
|
private:
|
||||||
virtual int process_request(SrsStSocket* skt, SrsHttpMessage* req);
|
virtual int process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -550,11 +550,6 @@ int SrsHttpConn::process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// parse uri to schema/server:port/path?query
|
|
||||||
if ((ret = req->parse_uri()) != ERROR_SUCCESS) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
srs_trace("HTTP %s %s, content-length=%"PRId64"",
|
srs_trace("HTTP %s %s, content-length=%"PRId64"",
|
||||||
req->method_str().c_str(), req->url().c_str(), req->content_length());
|
req->method_str().c_str(), req->url().c_str(), req->content_length());
|
||||||
|
|
||||||
|
|
|
@ -330,7 +330,7 @@ SrsServer::SrsServer()
|
||||||
// for some global instance is not ready now,
|
// for some global instance is not ready now,
|
||||||
// new these objects in initialize instead.
|
// new these objects in initialize instead.
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
#ifdef SRS_AUTO_HTTP_API
|
||||||
http_api_handler = NULL;
|
http_api_mux = new SrsGoHttpServeMux();
|
||||||
#endif
|
#endif
|
||||||
#ifdef SRS_AUTO_HTTP_SERVER
|
#ifdef SRS_AUTO_HTTP_SERVER
|
||||||
http_stream_handler = NULL;
|
http_stream_handler = NULL;
|
||||||
|
@ -363,7 +363,7 @@ void SrsServer::destroy()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
#ifdef SRS_AUTO_HTTP_API
|
||||||
srs_freep(http_api_handler);
|
srs_freep(http_api_mux);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_SERVER
|
#ifdef SRS_AUTO_HTTP_SERVER
|
||||||
|
@ -415,8 +415,52 @@ int SrsServer::initialize()
|
||||||
kbps->set_io(NULL, NULL);
|
kbps->set_io(NULL, NULL);
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
#ifdef SRS_AUTO_HTTP_API
|
||||||
srs_assert(!http_api_handler);
|
if ((ret = http_api_mux->initialize()) != ERROR_SUCCESS) {
|
||||||
http_api_handler = SrsHttpHandler::create_http_api();
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SRS_AUTO_HTTP_API
|
||||||
|
srs_assert(http_api_mux);
|
||||||
|
if ((ret = http_api_mux->handle("/", new SrsGoApiRoot())) != 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/requests", new SrsGoApiRequests())) != 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;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef SRS_AUTO_HTTP_SERVER
|
#ifdef SRS_AUTO_HTTP_SERVER
|
||||||
srs_assert(!http_stream_handler);
|
srs_assert(!http_stream_handler);
|
||||||
|
@ -431,12 +475,6 @@ int SrsServer::initialize()
|
||||||
ingester = new SrsIngester();
|
ingester = new SrsIngester();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
|
||||||
if ((ret = http_api_handler->initialize()) != ERROR_SUCCESS) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SRS_AUTO_HTTP_SERVER
|
#ifdef SRS_AUTO_HTTP_SERVER
|
||||||
if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) {
|
if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -896,7 +934,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
|
||||||
conn = new SrsRtmpConn(this, client_stfd);
|
conn = new SrsRtmpConn(this, client_stfd);
|
||||||
} else if (type == SrsListenerHttpApi) {
|
} else if (type == SrsListenerHttpApi) {
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
#ifdef SRS_AUTO_HTTP_API
|
||||||
conn = new SrsHttpApi(this, client_stfd, http_api_handler);
|
conn = new SrsHttpApi(this, client_stfd, http_api_mux);
|
||||||
#else
|
#else
|
||||||
srs_warn("close http client for server not support http-api");
|
srs_warn("close http client for server not support http-api");
|
||||||
srs_close_stfd(client_stfd);
|
srs_close_stfd(client_stfd);
|
||||||
|
|
|
@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
class SrsServer;
|
class SrsServer;
|
||||||
class SrsConnection;
|
class SrsConnection;
|
||||||
|
class SrsGoHttpServeMux;
|
||||||
class SrsHttpHandler;
|
class SrsHttpHandler;
|
||||||
class SrsIngester;
|
class SrsIngester;
|
||||||
class SrsHttpHeartbeat;
|
class SrsHttpHeartbeat;
|
||||||
|
@ -116,7 +117,7 @@ class SrsServer : public ISrsReloadHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
#ifdef SRS_AUTO_HTTP_API
|
#ifdef SRS_AUTO_HTTP_API
|
||||||
SrsHttpHandler* http_api_handler;
|
SrsGoHttpServeMux* http_api_mux;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SRS_AUTO_HTTP_SERVER
|
#ifdef SRS_AUTO_HTTP_SERVER
|
||||||
SrsHttpHandler* http_stream_handler;
|
SrsHttpHandler* http_stream_handler;
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR 2
|
#define VERSION_MAJOR 2
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 95
|
#define VERSION_REVISION 96
|
||||||
|
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "SRS"
|
#define RTMP_SIG_SRS_KEY "SRS"
|
||||||
|
|
|
@ -204,6 +204,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#define ERROR_AAC_DATA_INVALID 3048
|
#define ERROR_AAC_DATA_INVALID 3048
|
||||||
#define ERROR_HTTP_STATUS_INVLIAD 3049
|
#define ERROR_HTTP_STATUS_INVLIAD 3049
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
// HTTP protocol error.
|
||||||
|
///////////////////////////////////////////////////////
|
||||||
|
#define ERROR_HTTP_PATTERN_EMPTY 4000
|
||||||
|
#define ERROR_HTTP_PATTERN_DUPLICATED 4001
|
||||||
|
#define ERROR_HTTP_URL_NOT_CLEAN 4002
|
||||||
|
#define ERROR_HTTP_CONTENT_LENGTH 4003
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether the error code is an system control error.
|
* whether the error code is an system control error.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue