diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index 991ca16f8..6fb92e1c8 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -59,7 +59,7 @@ int SrsHttpHandler::initialize() return ret; } -bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/) +bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/, const char** /*pnext_path*/) { return false; } @@ -86,20 +86,23 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph } // whether the handler can handler the node. - int node_size = p - path; - if (!can_handle(path, node_size)) { + const char* pnext = p; + if (!can_handle(path, p - path, &pnext)) { break; } + // save current handler, it's ok for current handler atleast. *phandler = this; *pstart = path; - *plength = node_size; + *plength = p - path; + // find the best matched child handler. std::vector::iterator it; for (it = handlers.begin(); it != handlers.end(); ++it) { SrsHttpHandler* handler = *it; - // matched, donot search. - if (handler->best_match(p, length - node_size, phandler, pstart, plength) == ERROR_SUCCESS) { + + // matched, donot search more. + if (handler->best_match(pnext, length - (pnext - path), phandler, pstart, plength) == ERROR_SUCCESS) { break; } } @@ -116,6 +119,76 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph return ret; } +SrsHttpHandler* SrsHttpHandler::res_status_line(std::stringstream& ss) +{ + ss << "HTTP/1.1 200 OK " << __CRLF + << "Server: SRS/"RTMP_SIG_SRS_VERSION"" << __CRLF; + return this; +} + +SrsHttpHandler* SrsHttpHandler::res_content_type(std::stringstream& ss) +{ + ss << "Content-Type: text/html;charset=utf-8" << __CRLF + << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __CRLF; + return this; +} + +SrsHttpHandler* SrsHttpHandler::res_content_length(std::stringstream& ss, int64_t length) +{ + ss << "Content-Length: "<< length << __CRLF; + return this; +} + +SrsHttpHandler* SrsHttpHandler::res_enable_crossdomain(std::stringstream& ss) +{ + ss << "Access-Control-Allow-Origin: *" << __CRLF + << "Access-Control-Allow-Methods: " + << "GET, POST, HEAD, PUT, DELETE" << __CRLF + << "Access-Control-Allow-Headers: " + << "Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type" << __CRLF; + return this; +} + +SrsHttpHandler* SrsHttpHandler::res_header_eof(std::stringstream& ss) +{ + ss << __CRLF; + return this; +} + +SrsHttpHandler* SrsHttpHandler::res_body(std::stringstream& ss, std::string body) +{ + ss << body; + return this; +} + +int SrsHttpHandler::res_flush(SrsSocket* skt, std::stringstream& ss) +{ + return skt->write(ss.str().c_str(), ss.str().length(), NULL); +} + +int SrsHttpHandler::res_options(SrsSocket* skt) +{ + std::stringstream ss; + + res_status_line(ss)->res_content_type(ss) + ->res_content_length(ss, 0)->res_enable_crossdomain(ss) + ->res_header_eof(ss); + + return res_flush(skt, ss); +} + +int SrsHttpHandler::res_text(SrsSocket* skt, std::string body) +{ + std::stringstream ss; + + res_status_line(ss)->res_content_type(ss) + ->res_content_length(ss, (int)body.length())->res_enable_crossdomain(ss) + ->res_header_eof(ss) + ->res_body(ss, body); + + return res_flush(skt, ss); +} + SrsHttpHandler* SrsHttpHandler::create_http_api() { return new SrsApiRoot(); diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index 0559c14f4..1b569f794 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -33,6 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include #include @@ -89,8 +90,9 @@ public: virtual int initialize(); /** * whether current handler can handle the specified path. + * @pnext_path set the next path, if needed. */ - virtual bool can_handle(const char* path, int length); + virtual bool can_handle(const char* path, int length, const char** pnext_path); /** * use the handler to process the request. */ @@ -100,6 +102,17 @@ public: * find the best matched handler */ virtual int best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength); +public: + virtual SrsHttpHandler* res_status_line(std::stringstream& ss); + virtual SrsHttpHandler* res_content_type(std::stringstream& ss); + virtual SrsHttpHandler* res_content_length(std::stringstream& ss, int64_t length); + virtual SrsHttpHandler* res_enable_crossdomain(std::stringstream& ss); + virtual SrsHttpHandler* res_header_eof(std::stringstream& ss); + virtual SrsHttpHandler* res_body(std::stringstream& ss, std::string body); + virtual int res_flush(SrsSocket* skt, std::stringstream& ss); +public: + virtual int res_options(SrsSocket* skt); + virtual int res_text(SrsSocket* skt, std::string body); public: /** * create http api resource handler. diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 0b505244b..0a74091a9 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -36,21 +36,56 @@ using namespace std; SrsApiRoot::SrsApiRoot() { + handlers.push_back(new SrsApiApi()); } SrsApiRoot::~SrsApiRoot() { } -bool SrsApiRoot::can_handle(const char* /*path*/, int /*length*/) +bool SrsApiRoot::can_handle(const char* path, int length, const char** pnext_path) { + // reset the next path for child to parse. + *pnext_path = path; + return true; } -int SrsApiRoot::process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/, const char* /*path*/, int /*length*/) +int SrsApiRoot::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/) { - int ret = ERROR_SUCCESS; - return ret; + if (req->method() == HTTP_OPTIONS) { + return res_options(skt); + } else { + std::string body = "hello, root"; + return res_text(skt, body); + } + + return ERROR_SUCCESS; +} + +SrsApiApi::SrsApiApi() +{ +} + +SrsApiApi::~SrsApiApi() +{ +} + +bool SrsApiApi::can_handle(const char* path, int length, const char** /*pnext_path*/) +{ + return !memcmp("/api", path, length); +} + +int SrsApiApi::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/) +{ + if (req->method() == HTTP_OPTIONS) { + return res_options(skt); + } else { + std::string body = "hello, api"; + return res_text(skt, body); + } + + return ERROR_SUCCESS; } SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler) @@ -135,35 +170,6 @@ int SrsHttpApi::process_request(SrsSocket* skt, SrsHttpMessage* req) return ret; } - if (req->method() == HTTP_OPTIONS) { - char data[] = "HTTP/1.1 200 OK" __CRLF - "Content-Length: 0"__CRLF - "Server: SRS/"RTMP_SIG_SRS_VERSION""__CRLF - "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT"__CRLF - "Access-Control-Allow-Origin: *"__CRLF - "Access-Control-Allow-Methods: GET, POST, HEAD, PUT, DELETE"__CRLF - "Access-Control-Allow-Headers: Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type"__CRLF - "Content-Type: text/html;charset=utf-8"__CRLFCRLF - ""; - return skt->write(data, sizeof(data), NULL); - } else { - std::string tilte = "SRS/"RTMP_SIG_SRS_VERSION; - tilte += " hello http/1.1 api~\n"; - - std::stringstream ss; - ss << "HTTP/1.1 200 OK " << __CRLF - << "Content-Length: "<< tilte.length() + req->body_size() << __CRLF - << "Server: SRS/"RTMP_SIG_SRS_VERSION"" << __CRLF - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __CRLF - << "Access-Control-Allow-Origin: *" << __CRLF - << "Access-Control-Allow-Methods: GET, POST, HEAD, PUT, DELETE" << __CRLF - << "Access-Control-Allow-Headers: Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type" << __CRLF - << "Content-Type: text/html;charset=utf-8" << __CRLFCRLF - << tilte << req->body().c_str() - << ""; - return skt->write(ss.str().c_str(), ss.str().length(), NULL); - } - return ret; } diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index 743a91d45..8d1f17517 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -48,7 +48,17 @@ public: SrsApiRoot(); virtual ~SrsApiRoot(); public: - virtual bool can_handle(const char* path, int length); + virtual bool can_handle(const char* path, int length, const char** pnext_path); + virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length); +}; + +class SrsApiApi : public SrsHttpHandler +{ +public: + SrsApiApi(); + virtual ~SrsApiApi(); +public: + virtual bool can_handle(const char* path, int length, const char** pnext_path); virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length); };