正在显示
5 个修改的文件
包含
172 行增加
和
0 行删除
| @@ -34,6 +34,7 @@ using namespace std; | @@ -34,6 +34,7 @@ using namespace std; | ||
| 34 | #include <srs_app_socket.hpp> | 34 | #include <srs_app_socket.hpp> |
| 35 | #include <srs_app_http_api.hpp> | 35 | #include <srs_app_http_api.hpp> |
| 36 | #include <srs_app_http_conn.hpp> | 36 | #include <srs_app_http_conn.hpp> |
| 37 | +#include <srs_app_json.hpp> | ||
| 37 | 38 | ||
| 38 | #define SRS_DEFAULT_HTTP_PORT 80 | 39 | #define SRS_DEFAULT_HTTP_PORT 80 |
| 39 | 40 | ||
| @@ -85,10 +86,39 @@ int SrsHttpHandler::process_request(SrsSocket* skt, SrsHttpMessage* req) | @@ -85,10 +86,39 @@ int SrsHttpHandler::process_request(SrsSocket* skt, SrsHttpMessage* req) | ||
| 85 | if (req->method() == HTTP_OPTIONS) { | 86 | if (req->method() == HTTP_OPTIONS) { |
| 86 | return res_options(skt); | 87 | return res_options(skt); |
| 87 | } | 88 | } |
| 89 | + | ||
| 90 | + int status_code; | ||
| 91 | + std::string reason_phrase; | ||
| 92 | + if (!is_handler_valid(req, status_code, reason_phrase)) { | ||
| 93 | + std::stringstream ss; | ||
| 94 | + | ||
| 95 | + ss << JOBJECT_START | ||
| 96 | + << JFIELD_ERROR(ERROR_HTTP_HANDLER_INVALID) << JFIELD_CONT | ||
| 97 | + << JFIELD_ORG("data", JOBJECT_START) | ||
| 98 | + << JFIELD_ORG("status_code", status_code) << JFIELD_CONT | ||
| 99 | + << JFIELD_STR("reason_phrase", reason_phrase) << JFIELD_CONT | ||
| 100 | + << JFIELD_STR("url", req->url()) | ||
| 101 | + << JOBJECT_END | ||
| 102 | + << JOBJECT_END; | ||
| 103 | + | ||
| 104 | + return res_error(skt, status_code, reason_phrase, ss.str()); | ||
| 105 | + } | ||
| 88 | 106 | ||
| 89 | return do_process_request(skt, req); | 107 | return do_process_request(skt, req); |
| 90 | } | 108 | } |
| 91 | 109 | ||
| 110 | +bool SrsHttpHandler::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase) | ||
| 111 | +{ | ||
| 112 | + if (!req->match()->unmatched_url.empty()) { | ||
| 113 | + status_code = HTTP_NotFound; | ||
| 114 | + reason_phrase = HTTP_NotFound_str; | ||
| 115 | + | ||
| 116 | + return false; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + return true; | ||
| 120 | +} | ||
| 121 | + | ||
| 92 | int SrsHttpHandler::do_process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/) | 122 | int SrsHttpHandler::do_process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/) |
| 93 | { | 123 | { |
| 94 | int ret = ERROR_SUCCESS; | 124 | int ret = ERROR_SUCCESS; |
| @@ -156,6 +186,11 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandlerMatch | @@ -156,6 +186,11 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandlerMatch | ||
| 156 | (*ppmatch)->handler = handler; | 186 | (*ppmatch)->handler = handler; |
| 157 | (*ppmatch)->matched_url.append(match_start, match_length); | 187 | (*ppmatch)->matched_url.append(match_start, match_length); |
| 158 | 188 | ||
| 189 | + int unmatch_length = length - match_length; | ||
| 190 | + if (unmatch_length > 0) { | ||
| 191 | + (*ppmatch)->unmatched_url.append(match_start + match_length, unmatch_length); | ||
| 192 | + } | ||
| 193 | + | ||
| 159 | return ret; | 194 | return ret; |
| 160 | } | 195 | } |
| 161 | 196 | ||
| @@ -166,6 +201,13 @@ SrsHttpHandler* SrsHttpHandler::res_status_line(std::stringstream& ss) | @@ -166,6 +201,13 @@ SrsHttpHandler* SrsHttpHandler::res_status_line(std::stringstream& ss) | ||
| 166 | return this; | 201 | return this; |
| 167 | } | 202 | } |
| 168 | 203 | ||
| 204 | +SrsHttpHandler* SrsHttpHandler::res_status_line_error(std::stringstream& ss, int code, std::string reason_phrase) | ||
| 205 | +{ | ||
| 206 | + ss << "HTTP/1.1 " << code << " " << reason_phrase << __CRLF | ||
| 207 | + << "Server: SRS/"RTMP_SIG_SRS_VERSION"" << __CRLF; | ||
| 208 | + return this; | ||
| 209 | +} | ||
| 210 | + | ||
| 169 | SrsHttpHandler* SrsHttpHandler::res_content_type(std::stringstream& ss) | 211 | SrsHttpHandler* SrsHttpHandler::res_content_type(std::stringstream& ss) |
| 170 | { | 212 | { |
| 171 | ss << "Content-Type: text/html;charset=utf-8" << __CRLF | 213 | ss << "Content-Type: text/html;charset=utf-8" << __CRLF |
| @@ -248,6 +290,22 @@ int SrsHttpHandler::res_json(SrsSocket* skt, std::string json) | @@ -248,6 +290,22 @@ int SrsHttpHandler::res_json(SrsSocket* skt, std::string json) | ||
| 248 | return res_flush(skt, ss); | 290 | return res_flush(skt, ss); |
| 249 | } | 291 | } |
| 250 | 292 | ||
| 293 | +int SrsHttpHandler::res_error(SrsSocket* skt, int code, std::string reason_phrase, std::string body) | ||
| 294 | +{ | ||
| 295 | + std::stringstream ss; | ||
| 296 | + | ||
| 297 | + ss << "HTTP/1.1 " << code << " " << reason_phrase << __CRLF | ||
| 298 | + << "Server: SRS/"RTMP_SIG_SRS_VERSION"" << __CRLF; | ||
| 299 | + | ||
| 300 | + res_status_line_error(ss, code, reason_phrase) | ||
| 301 | + ->res_content_type_json(ss) | ||
| 302 | + ->res_content_length(ss, (int)body.length()) | ||
| 303 | + ->res_header_eof(ss) | ||
| 304 | + ->res_body(ss, body); | ||
| 305 | + | ||
| 306 | + return res_flush(skt, ss); | ||
| 307 | +} | ||
| 308 | + | ||
| 251 | SrsHttpHandler* SrsHttpHandler::create_http_api() | 309 | SrsHttpHandler* SrsHttpHandler::create_http_api() |
| 252 | { | 310 | { |
| 253 | return new SrsApiRoot(); | 311 | return new SrsApiRoot(); |
| @@ -62,6 +62,89 @@ class SrsHttpHandler; | @@ -62,6 +62,89 @@ class SrsHttpHandler; | ||
| 62 | #define __CRLF "\r\n" // 0x0D0A | 62 | #define __CRLF "\r\n" // 0x0D0A |
| 63 | #define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A | 63 | #define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A |
| 64 | 64 | ||
| 65 | +// 6.1.1 Status Code and Reason Phrase | ||
| 66 | +#define HTTP_Continue 100 | ||
| 67 | +#define HTTP_SwitchingProtocols 101 | ||
| 68 | +#define HTTP_OK 200 | ||
| 69 | +#define HTTP_Created 201 | ||
| 70 | +#define HTTP_Accepted 202 | ||
| 71 | +#define HTTP_NonAuthoritativeInformation 203 | ||
| 72 | +#define HTTP_NoContent 204 | ||
| 73 | +#define HTTP_ResetContent 205 | ||
| 74 | +#define HTTP_PartialContent 206 | ||
| 75 | +#define HTTP_MultipleChoices 300 | ||
| 76 | +#define HTTP_MovedPermanently 301 | ||
| 77 | +#define HTTP_Found 302 | ||
| 78 | +#define HTTP_SeeOther 303 | ||
| 79 | +#define HTTP_NotModified 304 | ||
| 80 | +#define HTTP_UseProxy 305 | ||
| 81 | +#define HTTP_TemporaryRedirect 307 | ||
| 82 | +#define HTTP_BadRequest 400 | ||
| 83 | +#define HTTP_Unauthorized 401 | ||
| 84 | +#define HTTP_PaymentRequired 402 | ||
| 85 | +#define HTTP_Forbidden 403 | ||
| 86 | +#define HTTP_NotFound 404 | ||
| 87 | +#define HTTP_MethodNotAllowed 405 | ||
| 88 | +#define HTTP_NotAcceptable 406 | ||
| 89 | +#define HTTP_ProxyAuthenticationRequired 407 | ||
| 90 | +#define HTTP_RequestTimeout 408 | ||
| 91 | +#define HTTP_Conflict 409 | ||
| 92 | +#define HTTP_Gone 410 | ||
| 93 | +#define HTTP_LengthRequired 411 | ||
| 94 | +#define HTTP_PreconditionFailed 412 | ||
| 95 | +#define HTTP_RequestEntityTooLarge 413 | ||
| 96 | +#define HTTP_RequestURITooLarge 414 | ||
| 97 | +#define HTTP_UnsupportedMediaType 415 | ||
| 98 | +#define HTTP_RequestedRangeNotSatisfiable 416 | ||
| 99 | +#define HTTP_ExpectationFailed 417 | ||
| 100 | +#define HTTP_InternalServerError 500 | ||
| 101 | +#define HTTP_NotImplemented 501 | ||
| 102 | +#define HTTP_BadGateway 502 | ||
| 103 | +#define HTTP_ServiceUnavailable 503 | ||
| 104 | +#define HTTP_GatewayTimeout 504 | ||
| 105 | +#define HTTP_HTTPVersionNotSupported 505 | ||
| 106 | + | ||
| 107 | +#define HTTP_Continue_str "Continue" | ||
| 108 | +#define HTTP_SwitchingProtocols_str "Switching Protocols" | ||
| 109 | +#define HTTP_OK_str "OK" | ||
| 110 | +#define HTTP_Created_str "Created " | ||
| 111 | +#define HTTP_Accepted_str "Accepted" | ||
| 112 | +#define HTTP_NonAuthoritativeInformation_str "Non Authoritative Information " | ||
| 113 | +#define HTTP_NoContent_str "No Content " | ||
| 114 | +#define HTTP_ResetContent_str "Reset Content" | ||
| 115 | +#define HTTP_PartialContent_str "Partial Content" | ||
| 116 | +#define HTTP_MultipleChoices_str "Multiple Choices " | ||
| 117 | +#define HTTP_MovedPermanently_str "Moved Permanently" | ||
| 118 | +#define HTTP_Found_str "Found" | ||
| 119 | +#define HTTP_SeeOther_str "See Other" | ||
| 120 | +#define HTTP_NotModified_str "Not Modified " | ||
| 121 | +#define HTTP_UseProxy_str "Use Proxy" | ||
| 122 | +#define HTTP_TemporaryRedirect_str "Temporary Redirect " | ||
| 123 | +#define HTTP_BadRequest_str "Bad Request" | ||
| 124 | +#define HTTP_Unauthorized_str "Unauthorized" | ||
| 125 | +#define HTTP_PaymentRequired_str "Payment Required " | ||
| 126 | +#define HTTP_Forbidden_str "Forbidden " | ||
| 127 | +#define HTTP_NotFound_str "Not Found" | ||
| 128 | +#define HTTP_MethodNotAllowed_str "Method Not Allowed" | ||
| 129 | +#define HTTP_NotAcceptable_str "Not Acceptable " | ||
| 130 | +#define HTTP_ProxyAuthenticationRequired_str "Proxy Authentication Required " | ||
| 131 | +#define HTTP_RequestTimeout_str "Request Timeout" | ||
| 132 | +#define HTTP_Conflict_str "Conflict" | ||
| 133 | +#define HTTP_Gone_str "Gone" | ||
| 134 | +#define HTTP_LengthRequired_str "Length Required" | ||
| 135 | +#define HTTP_PreconditionFailed_str "Precondition Failed" | ||
| 136 | +#define HTTP_RequestEntityTooLarge_str "Request Entity Too Large " | ||
| 137 | +#define HTTP_RequestURITooLarge_str "Request URI Too Large" | ||
| 138 | +#define HTTP_UnsupportedMediaType_str "Unsupported Media Type" | ||
| 139 | +#define HTTP_RequestedRangeNotSatisfiable_str "Requested Range Not Satisfiable" | ||
| 140 | +#define HTTP_ExpectationFailed_str "Expectation Failed " | ||
| 141 | +#define HTTP_InternalServerError_str "Internal Server Error " | ||
| 142 | +#define HTTP_NotImplemented_str "Not Implemented" | ||
| 143 | +#define HTTP_BadGateway_str "Bad Gateway" | ||
| 144 | +#define HTTP_ServiceUnavailable_str "Service Unavailable" | ||
| 145 | +#define HTTP_GatewayTimeout_str "Gateway Timeout" | ||
| 146 | +#define HTTP_HTTPVersionNotSupported_str "HTTP Version Not Supported" | ||
| 147 | + | ||
| 65 | // linux path seprator | 148 | // linux path seprator |
| 66 | #define __PATH_SEP '/' | 149 | #define __PATH_SEP '/' |
| 67 | // query string seprator | 150 | // query string seprator |
| @@ -86,6 +169,7 @@ class SrsHttpHandlerMatch | @@ -86,6 +169,7 @@ class SrsHttpHandlerMatch | ||
| 86 | public: | 169 | public: |
| 87 | SrsHttpHandler* handler; | 170 | SrsHttpHandler* handler; |
| 88 | std::string matched_url; | 171 | std::string matched_url; |
| 172 | + std::string unmatched_url; | ||
| 89 | public: | 173 | public: |
| 90 | SrsHttpHandlerMatch(); | 174 | SrsHttpHandlerMatch(); |
| 91 | }; | 175 | }; |
| @@ -127,10 +211,22 @@ public: | @@ -127,10 +211,22 @@ public: | ||
| 127 | virtual int best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch); | 211 | virtual int best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch); |
| 128 | // factory methods | 212 | // factory methods |
| 129 | protected: | 213 | protected: |
| 214 | + /** | ||
| 215 | + * check whether the handler is valid. | ||
| 216 | + * for example, user access /apis, actually it's not found, | ||
| 217 | + * we will find the root handler to process it. | ||
| 218 | + * @remark user can override this method, and should invoke it first. | ||
| 219 | + * @see SrsApiRoot::is_handler_valid | ||
| 220 | + */ | ||
| 221 | + virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase); | ||
| 222 | + /** | ||
| 223 | + * do the actual process of request. | ||
| 224 | + */ | ||
| 130 | virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req); | 225 | virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req); |
| 131 | // response writer | 226 | // response writer |
| 132 | public: | 227 | public: |
| 133 | virtual SrsHttpHandler* res_status_line(std::stringstream& ss); | 228 | virtual SrsHttpHandler* res_status_line(std::stringstream& ss); |
| 229 | + virtual SrsHttpHandler* res_status_line_error(std::stringstream& ss, int code, std::string reason_phrase); | ||
| 134 | virtual SrsHttpHandler* res_content_type(std::stringstream& ss); | 230 | virtual SrsHttpHandler* res_content_type(std::stringstream& ss); |
| 135 | virtual SrsHttpHandler* res_content_type_json(std::stringstream& ss); | 231 | virtual SrsHttpHandler* res_content_type_json(std::stringstream& ss); |
| 136 | virtual SrsHttpHandler* res_content_length(std::stringstream& ss, int64_t length); | 232 | virtual SrsHttpHandler* res_content_length(std::stringstream& ss, int64_t length); |
| @@ -142,6 +238,7 @@ public: | @@ -142,6 +238,7 @@ public: | ||
| 142 | virtual int res_options(SrsSocket* skt); | 238 | virtual int res_options(SrsSocket* skt); |
| 143 | virtual int res_text(SrsSocket* skt, std::string body); | 239 | virtual int res_text(SrsSocket* skt, std::string body); |
| 144 | virtual int res_json(SrsSocket* skt, std::string json); | 240 | virtual int res_json(SrsSocket* skt, std::string json); |
| 241 | + virtual int res_error(SrsSocket* skt, int code, std::string reason_phrase, std::string body); | ||
| 145 | // object creator | 242 | // object creator |
| 146 | public: | 243 | public: |
| 147 | /** | 244 | /** |
| @@ -44,6 +44,21 @@ SrsApiRoot::~SrsApiRoot() | @@ -44,6 +44,21 @@ SrsApiRoot::~SrsApiRoot() | ||
| 44 | { | 44 | { |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | +bool SrsApiRoot::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase) | ||
| 48 | +{ | ||
| 49 | + if (!SrsHttpHandler::is_handler_valid(req, status_code, reason_phrase)) { | ||
| 50 | + return false; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + if (req->match()->matched_url.length() != 1) { | ||
| 54 | + status_code = HTTP_NotFound; | ||
| 55 | + reason_phrase = HTTP_NotFound_str; | ||
| 56 | + return false; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + return true; | ||
| 60 | +} | ||
| 61 | + | ||
| 47 | bool SrsApiRoot::can_handle(const char* path, int length, const char** pchild) | 62 | bool SrsApiRoot::can_handle(const char* path, int length, const char** pchild) |
| 48 | { | 63 | { |
| 49 | // reset the child path to path, | 64 | // reset the child path to path, |
| @@ -48,6 +48,7 @@ public: | @@ -48,6 +48,7 @@ public: | ||
| 48 | SrsApiRoot(); | 48 | SrsApiRoot(); |
| 49 | virtual ~SrsApiRoot(); | 49 | virtual ~SrsApiRoot(); |
| 50 | public: | 50 | public: |
| 51 | + virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase); | ||
| 51 | virtual bool can_handle(const char* path, int length, const char** pchild); | 52 | virtual bool can_handle(const char* path, int length, const char** pchild); |
| 52 | virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req); | 53 | virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req); |
| 53 | }; | 54 | }; |
| @@ -158,6 +158,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -158,6 +158,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 158 | #define ERROR_HTTP_DATA_INVLIAD 801 | 158 | #define ERROR_HTTP_DATA_INVLIAD 801 |
| 159 | #define ERROR_HTTP_PARSE_HEADER 802 | 159 | #define ERROR_HTTP_PARSE_HEADER 802 |
| 160 | #define ERROR_HTTP_HANDLER_MATCH_URL 803 | 160 | #define ERROR_HTTP_HANDLER_MATCH_URL 803 |
| 161 | +#define ERROR_HTTP_HANDLER_INVALID 804 | ||
| 161 | 162 | ||
| 162 | // system control message, | 163 | // system control message, |
| 163 | // not an error, but special control logic. | 164 | // not an error, but special control logic. |
-
请 注册 或 登录 后发表评论