winlin

support http error code, check url

@@ -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.