winlin

refine the http url handler match. refine json encode

@@ -427,7 +427,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke @@ -427,7 +427,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke
427 "srs_app_codec" "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder" 427 "srs_app_codec" "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder"
428 "srs_app_http" "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" 428 "srs_app_http" "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log"
429 "srs_app_config" "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" 429 "srs_app_config" "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api"
430 - "srs_app_http_conn" "srs_app_http_hooks") 430 + "srs_app_http_conn" "srs_app_http_hooks" "srs_app_json")
431 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh 431 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
432 APP_OBJS="${MODULE_OBJS[@]}" 432 APP_OBJS="${MODULE_OBJS[@]}"
433 # 433 #
@@ -39,6 +39,22 @@ using namespace std; @@ -39,6 +39,22 @@ using namespace std;
39 39
40 #define SRS_HTTP_HEADER_BUFFER 1024 40 #define SRS_HTTP_HEADER_BUFFER 1024
41 41
  42 +bool srs_path_equals(const char* expect, const char* path, int nb_path)
  43 +{
  44 + int size = strlen(expect);
  45 +
  46 + if (size != nb_path) {
  47 + return false;
  48 + }
  49 +
  50 + return !memcmp(expect, path, size);
  51 +}
  52 +
  53 +SrsHttpHandlerMatch::SrsHttpHandlerMatch()
  54 +{
  55 + handler = NULL;
  56 +}
  57 +
42 SrsHttpHandler::SrsHttpHandler() 58 SrsHttpHandler::SrsHttpHandler()
43 { 59 {
44 } 60 }
@@ -59,21 +75,34 @@ int SrsHttpHandler::initialize() @@ -59,21 +75,34 @@ int SrsHttpHandler::initialize()
59 return ret; 75 return ret;
60 } 76 }
61 77
62 -bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/, const char** /*pnext_path*/) 78 +bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/, const char** /*pchild*/)
63 { 79 {
64 return false; 80 return false;
65 } 81 }
66 82
67 -int SrsHttpHandler::process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/, const char* /*path*/, int /*length*/) 83 +int SrsHttpHandler::process_request(SrsSocket* skt, SrsHttpMessage* req)
  84 +{
  85 + if (req->method() == HTTP_OPTIONS) {
  86 + return res_options(skt);
  87 + }
  88 +
  89 + return do_process_request(skt, req);
  90 +}
  91 +
  92 +int SrsHttpHandler::do_process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/)
68 { 93 {
69 int ret = ERROR_SUCCESS; 94 int ret = ERROR_SUCCESS;
70 return ret; 95 return ret;
71 } 96 }
72 97
73 -int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength) 98 +int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch)
74 { 99 {
75 int ret = ERROR_SUCCESS; 100 int ret = ERROR_SUCCESS;
76 101
  102 + SrsHttpHandler* handler = NULL;
  103 + const char* match_start = NULL;
  104 + int match_length = 0;
  105 +
77 for (;;) { 106 for (;;) {
78 // ensure cur is not NULL. 107 // ensure cur is not NULL.
79 // ensure p not NULL and has bytes to parse. 108 // ensure p not NULL and has bytes to parse.
@@ -86,23 +115,23 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph @@ -86,23 +115,23 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
86 } 115 }
87 116
88 // whether the handler can handler the node. 117 // whether the handler can handler the node.
89 - const char* pnext = p;  
90 - if (!can_handle(path, p - path, &pnext)) { 118 + const char* pchild = p;
  119 + if (!can_handle(path, p - path, &pchild)) {
91 break; 120 break;
92 } 121 }
93 122
94 // save current handler, it's ok for current handler atleast. 123 // save current handler, it's ok for current handler atleast.
95 - *phandler = this;  
96 - *pstart = path;  
97 - *plength = p - path; 124 + handler = this;
  125 + match_start = path;
  126 + match_length = p - path;
98 127
99 // find the best matched child handler. 128 // find the best matched child handler.
100 std::vector<SrsHttpHandler*>::iterator it; 129 std::vector<SrsHttpHandler*>::iterator it;
101 for (it = handlers.begin(); it != handlers.end(); ++it) { 130 for (it = handlers.begin(); it != handlers.end(); ++it) {
102 - SrsHttpHandler* handler = *it; 131 + SrsHttpHandler* h = *it;
103 132
104 // matched, donot search more. 133 // matched, donot search more.
105 - if (handler->best_match(pnext, length - (pnext - path), phandler, pstart, plength) == ERROR_SUCCESS) { 134 + if (h->best_match(pchild, length - (pchild - path), ppmatch) == ERROR_SUCCESS) {
106 break; 135 break;
107 } 136 }
108 } 137 }
@@ -111,11 +140,22 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph @@ -111,11 +140,22 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
111 break; 140 break;
112 } 141 }
113 142
114 - if (*phandler == NULL) { 143 + // if already matched by child, return.
  144 + if (*ppmatch) {
  145 + return ret;
  146 + }
  147 +
  148 + // not matched, error.
  149 + if (handler == NULL) {
115 ret = ERROR_HTTP_HANDLER_MATCH_URL; 150 ret = ERROR_HTTP_HANDLER_MATCH_URL;
116 return ret; 151 return ret;
117 } 152 }
118 153
  154 + // matched by this handler.
  155 + *ppmatch = new SrsHttpHandlerMatch();
  156 + (*ppmatch)->handler = handler;
  157 + (*ppmatch)->matched_url.append(match_start, match_length);
  158 +
119 return ret; 159 return ret;
120 } 160 }
121 161
@@ -133,6 +173,13 @@ SrsHttpHandler* SrsHttpHandler::res_content_type(std::stringstream& ss) @@ -133,6 +173,13 @@ SrsHttpHandler* SrsHttpHandler::res_content_type(std::stringstream& ss)
133 return this; 173 return this;
134 } 174 }
135 175
  176 +SrsHttpHandler* SrsHttpHandler::res_content_type_json(std::stringstream& ss)
  177 +{
  178 + ss << "Content-Type: application/json;charset=utf-8" << __CRLF
  179 + << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __CRLF;
  180 + return this;
  181 +}
  182 +
136 SrsHttpHandler* SrsHttpHandler::res_content_length(std::stringstream& ss, int64_t length) 183 SrsHttpHandler* SrsHttpHandler::res_content_length(std::stringstream& ss, int64_t length)
137 { 184 {
138 ss << "Content-Length: "<< length << __CRLF; 185 ss << "Content-Length: "<< length << __CRLF;
@@ -189,6 +236,18 @@ int SrsHttpHandler::res_text(SrsSocket* skt, std::string body) @@ -189,6 +236,18 @@ int SrsHttpHandler::res_text(SrsSocket* skt, std::string body)
189 return res_flush(skt, ss); 236 return res_flush(skt, ss);
190 } 237 }
191 238
  239 +int SrsHttpHandler::res_json(SrsSocket* skt, std::string json)
  240 +{
  241 + std::stringstream ss;
  242 +
  243 + res_status_line(ss)->res_content_type_json(ss)
  244 + ->res_content_length(ss, (int)json.length())->res_enable_crossdomain(ss)
  245 + ->res_header_eof(ss)
  246 + ->res_body(ss, json);
  247 +
  248 + return res_flush(skt, ss);
  249 +}
  250 +
192 SrsHttpHandler* SrsHttpHandler::create_http_api() 251 SrsHttpHandler* SrsHttpHandler::create_http_api()
193 { 252 {
194 return new SrsApiRoot(); 253 return new SrsApiRoot();
@@ -204,11 +263,15 @@ SrsHttpMessage::SrsHttpMessage() @@ -204,11 +263,15 @@ SrsHttpMessage::SrsHttpMessage()
204 { 263 {
205 _body = new SrsBuffer(); 264 _body = new SrsBuffer();
206 _state = SrsHttpParseStateInit; 265 _state = SrsHttpParseStateInit;
  266 + _uri = new SrsHttpUri();
  267 + _match = NULL;
207 } 268 }
208 269
209 SrsHttpMessage::~SrsHttpMessage() 270 SrsHttpMessage::~SrsHttpMessage()
210 { 271 {
211 srs_freep(_body); 272 srs_freep(_body);
  273 + srs_freep(_uri);
  274 + srs_freep(_match);
212 } 275 }
213 276
214 void SrsHttpMessage::reset() 277 void SrsHttpMessage::reset()
@@ -218,6 +281,11 @@ void SrsHttpMessage::reset() @@ -218,6 +281,11 @@ void SrsHttpMessage::reset()
218 _url = ""; 281 _url = "";
219 } 282 }
220 283
  284 +int SrsHttpMessage::parse_uri()
  285 +{
  286 + return _uri->initialize(_url);
  287 +}
  288 +
221 bool SrsHttpMessage::is_complete() 289 bool SrsHttpMessage::is_complete()
222 { 290 {
223 return _state == SrsHttpParseStateComplete; 291 return _state == SrsHttpParseStateComplete;
@@ -230,7 +298,17 @@ u_int8_t SrsHttpMessage::method() @@ -230,7 +298,17 @@ u_int8_t SrsHttpMessage::method()
230 298
231 string SrsHttpMessage::url() 299 string SrsHttpMessage::url()
232 { 300 {
233 - return _url; 301 + return _uri->get_url();
  302 +}
  303 +
  304 +string SrsHttpMessage::path()
  305 +{
  306 + return _uri->get_path();
  307 +}
  308 +
  309 +string SrsHttpMessage::query()
  310 +{
  311 + return _uri->get_query();
234 } 312 }
235 313
236 string SrsHttpMessage::body() 314 string SrsHttpMessage::body()
@@ -254,6 +332,11 @@ int64_t SrsHttpMessage::content_length() @@ -254,6 +332,11 @@ int64_t SrsHttpMessage::content_length()
254 return _header.content_length; 332 return _header.content_length;
255 } 333 }
256 334
  335 +SrsHttpHandlerMatch* SrsHttpMessage::match()
  336 +{
  337 + return _match;
  338 +}
  339 +
257 void SrsHttpMessage::set_url(std::string url) 340 void SrsHttpMessage::set_url(std::string url)
258 { 341 {
259 _url = url; 342 _url = url;
@@ -269,6 +352,12 @@ void SrsHttpMessage::set_header(http_parser* header) @@ -269,6 +352,12 @@ void SrsHttpMessage::set_header(http_parser* header)
269 memcpy(&_header, header, sizeof(http_parser)); 352 memcpy(&_header, header, sizeof(http_parser));
270 } 353 }
271 354
  355 +void SrsHttpMessage::set_match(SrsHttpHandlerMatch* match)
  356 +{
  357 + srs_freep(_match);
  358 + _match = match;
  359 +}
  360 +
272 void SrsHttpMessage::append_body(const char* body, int length) 361 void SrsHttpMessage::append_body(const char* body, int length)
273 { 362 {
274 _body->append(body, length); 363 _body->append(body, length);
@@ -489,22 +578,25 @@ int SrsHttpUri::initialize(std::string _url) @@ -489,22 +578,25 @@ int SrsHttpUri::initialize(std::string _url)
489 path = get_uri_field(url, &hp_u, UF_PATH); 578 path = get_uri_field(url, &hp_u, UF_PATH);
490 srs_info("parse url %s success", purl); 579 srs_info("parse url %s success", purl);
491 580
  581 + query = get_uri_field(url, &hp_u, UF_QUERY);
  582 + srs_trace("parse query %s success", purl);
  583 +
492 return ret; 584 return ret;
493 } 585 }
494 586
495 const char* SrsHttpUri::get_url() 587 const char* SrsHttpUri::get_url()
496 { 588 {
497 - return url.c_str(); 589 + return url.data();
498 } 590 }
499 591
500 const char* SrsHttpUri::get_schema() 592 const char* SrsHttpUri::get_schema()
501 { 593 {
502 - return schema.c_str(); 594 + return schema.data();
503 } 595 }
504 596
505 const char* SrsHttpUri::get_host() 597 const char* SrsHttpUri::get_host()
506 { 598 {
507 - return host.c_str(); 599 + return host.data();
508 } 600 }
509 601
510 int SrsHttpUri::get_port() 602 int SrsHttpUri::get_port()
@@ -514,7 +606,12 @@ int SrsHttpUri::get_port() @@ -514,7 +606,12 @@ int SrsHttpUri::get_port()
514 606
515 const char* SrsHttpUri::get_path() 607 const char* SrsHttpUri::get_path()
516 { 608 {
517 - return path.c_str(); 609 + return path.data();
  610 +}
  611 +
  612 +const char* SrsHttpUri::get_query()
  613 +{
  614 + return path.data();
518 } 615 }
519 616
520 std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field) 617 std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field)
@@ -42,7 +42,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -42,7 +42,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 class SrsBuffer; 42 class SrsBuffer;
43 class SrsRequest; 43 class SrsRequest;
44 class SrsSocket; 44 class SrsSocket;
  45 +class SrsHttpUri;
45 class SrsHttpMessage; 46 class SrsHttpMessage;
  47 +class SrsHttpHandler;
46 48
47 // http specification 49 // http specification
48 // CR = <US-ASCII CR, carriage return (13)> 50 // CR = <US-ASCII CR, carriage return (13)>
@@ -62,6 +64,12 @@ class SrsHttpMessage; @@ -62,6 +64,12 @@ class SrsHttpMessage;
62 64
63 // linux path seprator 65 // linux path seprator
64 #define __PATH_SEP '/' 66 #define __PATH_SEP '/'
  67 +// query string seprator
  68 +#define __QUERY_SEP '?'
  69 +
  70 +// compare the path.
  71 +// full compare, extractly match.
  72 +extern bool srs_path_equals(const char* expect, const char* path, int nb_path);
65 73
66 // state of message 74 // state of message
67 enum SrsHttpParseState { 75 enum SrsHttpParseState {
@@ -71,6 +79,18 @@ enum SrsHttpParseState { @@ -71,6 +79,18 @@ enum SrsHttpParseState {
71 }; 79 };
72 80
73 /** 81 /**
  82 +* the matched handler info.
  83 +*/
  84 +class SrsHttpHandlerMatch
  85 +{
  86 +public:
  87 + SrsHttpHandler* handler;
  88 + std::string matched_url;
  89 +public:
  90 + SrsHttpHandlerMatch();
  91 +};
  92 +
  93 +/**
74 * resource handler for HTTP RESTful api. 94 * resource handler for HTTP RESTful api.
75 */ 95 */
76 class SrsHttpHandler 96 class SrsHttpHandler
@@ -90,21 +110,29 @@ public: @@ -90,21 +110,29 @@ public:
90 virtual int initialize(); 110 virtual int initialize();
91 /** 111 /**
92 * whether current handler can handle the specified path. 112 * whether current handler can handle the specified path.
93 - * @pnext_path set the next path, if needed. 113 + * @pchild set the next child path, if needed.
  114 + * for example, the root handler will reset pchild to path,
  115 + * to reparse the path use child handlers.
94 */ 116 */
95 - virtual bool can_handle(const char* path, int length, const char** pnext_path); 117 + virtual bool can_handle(const char* path, int length, const char** pchild);
96 /** 118 /**
97 * use the handler to process the request. 119 * use the handler to process the request.
  120 + * @remark sub classes should override the do_process_request.
98 */ 121 */
99 - virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length); 122 + virtual int process_request(SrsSocket* skt, SrsHttpMessage* req);
100 public: 123 public:
101 /** 124 /**
102 * find the best matched handler 125 * find the best matched handler
103 */ 126 */
104 - virtual int best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength); 127 + virtual int best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch);
  128 +// factory methods
  129 +protected:
  130 + virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
  131 +// response writer
105 public: 132 public:
106 virtual SrsHttpHandler* res_status_line(std::stringstream& ss); 133 virtual SrsHttpHandler* res_status_line(std::stringstream& ss);
107 virtual SrsHttpHandler* res_content_type(std::stringstream& ss); 134 virtual SrsHttpHandler* res_content_type(std::stringstream& ss);
  135 + virtual SrsHttpHandler* res_content_type_json(std::stringstream& ss);
108 virtual SrsHttpHandler* res_content_length(std::stringstream& ss, int64_t length); 136 virtual SrsHttpHandler* res_content_length(std::stringstream& ss, int64_t length);
109 virtual SrsHttpHandler* res_enable_crossdomain(std::stringstream& ss); 137 virtual SrsHttpHandler* res_enable_crossdomain(std::stringstream& ss);
110 virtual SrsHttpHandler* res_header_eof(std::stringstream& ss); 138 virtual SrsHttpHandler* res_header_eof(std::stringstream& ss);
@@ -113,6 +141,8 @@ public: @@ -113,6 +141,8 @@ public:
113 public: 141 public:
114 virtual int res_options(SrsSocket* skt); 142 virtual int res_options(SrsSocket* skt);
115 virtual int res_text(SrsSocket* skt, std::string body); 143 virtual int res_text(SrsSocket* skt, std::string body);
  144 + virtual int res_json(SrsSocket* skt, std::string json);
  145 +// object creator
116 public: 146 public:
117 /** 147 /**
118 * create http api resource handler. 148 * create http api resource handler.
@@ -148,23 +178,34 @@ private: @@ -148,23 +178,34 @@ private:
148 * @remark, user can use is_complete() to determine the state. 178 * @remark, user can use is_complete() to determine the state.
149 */ 179 */
150 SrsHttpParseState _state; 180 SrsHttpParseState _state;
151 - 181 + /**
  182 + * uri parser
  183 + */
  184 + SrsHttpUri* _uri;
  185 + /**
  186 + * best matched handler.
  187 + */
  188 + SrsHttpHandlerMatch* _match;
152 public: 189 public:
153 SrsHttpMessage(); 190 SrsHttpMessage();
154 virtual ~SrsHttpMessage(); 191 virtual ~SrsHttpMessage();
155 -  
156 public: 192 public:
157 virtual void reset(); 193 virtual void reset();
  194 + virtual int parse_uri();
158 public: 195 public:
159 virtual bool is_complete(); 196 virtual bool is_complete();
160 virtual u_int8_t method(); 197 virtual u_int8_t method();
161 virtual std::string url(); 198 virtual std::string url();
  199 + virtual std::string path();
  200 + virtual std::string query();
162 virtual std::string body(); 201 virtual std::string body();
163 virtual int64_t body_size(); 202 virtual int64_t body_size();
164 virtual int64_t content_length(); 203 virtual int64_t content_length();
  204 + virtual SrsHttpHandlerMatch* match();
165 virtual void set_url(std::string url); 205 virtual void set_url(std::string url);
166 virtual void set_state(SrsHttpParseState state); 206 virtual void set_state(SrsHttpParseState state);
167 virtual void set_header(http_parser* header); 207 virtual void set_header(http_parser* header);
  208 + virtual void set_match(SrsHttpHandlerMatch* match);
168 virtual void append_body(const char* body, int length); 209 virtual void append_body(const char* body, int length);
169 }; 210 };
170 211
@@ -220,6 +261,7 @@ private: @@ -220,6 +261,7 @@ private:
220 std::string host; 261 std::string host;
221 int port; 262 int port;
222 std::string path; 263 std::string path;
  264 + std::string query;
223 public: 265 public:
224 SrsHttpUri(); 266 SrsHttpUri();
225 virtual ~SrsHttpUri(); 267 virtual ~SrsHttpUri();
@@ -234,6 +276,7 @@ public: @@ -234,6 +276,7 @@ public:
234 virtual const char* get_host(); 276 virtual const char* get_host();
235 virtual int get_port(); 277 virtual int get_port();
236 virtual const char* get_path(); 278 virtual const char* get_path();
  279 + virtual const char* get_query();
237 private: 280 private:
238 /** 281 /**
239 * get the parsed url field. 282 * get the parsed url field.
@@ -33,6 +33,7 @@ using namespace std; @@ -33,6 +33,7 @@ using namespace std;
33 #include <srs_app_http.hpp> 33 #include <srs_app_http.hpp>
34 #include <srs_app_socket.hpp> 34 #include <srs_app_socket.hpp>
35 #include <srs_core_autofree.hpp> 35 #include <srs_core_autofree.hpp>
  36 +#include <srs_app_json.hpp>
36 37
37 SrsApiRoot::SrsApiRoot() 38 SrsApiRoot::SrsApiRoot()
38 { 39 {
@@ -43,24 +44,28 @@ SrsApiRoot::~SrsApiRoot() @@ -43,24 +44,28 @@ SrsApiRoot::~SrsApiRoot()
43 { 44 {
44 } 45 }
45 46
46 -bool SrsApiRoot::can_handle(const char* path, int length, const char** pnext_path) 47 +bool SrsApiRoot::can_handle(const char* path, int length, const char** pchild)
47 { 48 {
48 - // reset the next path for child to parse.  
49 - *pnext_path = path; 49 + // reset the child path to path,
  50 + // for child to reparse the path.
  51 + *pchild = path;
50 52
51 - return true; 53 + // only compare the first char.
  54 + return srs_path_equals("/", path, 1);
52 } 55 }
53 56
54 -int SrsApiRoot::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/) 57 +int SrsApiRoot::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
55 { 58 {
56 - if (req->method() == HTTP_OPTIONS) {  
57 - return res_options(skt);  
58 - } else {  
59 - std::string body = "hello, root";  
60 - return res_text(skt, body);  
61 - }  
62 -  
63 - return ERROR_SUCCESS; 59 + std::stringstream ss;
  60 +
  61 + ss << JOBJECT_START
  62 + << JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT
  63 + << JFIELD_ORG("urls", JOBJECT_START)
  64 + << JFIELD_STR("v1", "the api version 1.0")
  65 + << JOBJECT_END
  66 + << JOBJECT_END;
  67 +
  68 + return res_json(skt, ss.str());
64 } 69 }
65 70
66 SrsApiApi::SrsApiApi() 71 SrsApiApi::SrsApiApi()
@@ -71,21 +76,15 @@ SrsApiApi::~SrsApiApi() @@ -71,21 +76,15 @@ SrsApiApi::~SrsApiApi()
71 { 76 {
72 } 77 }
73 78
74 -bool SrsApiApi::can_handle(const char* path, int length, const char** /*pnext_path*/) 79 +bool SrsApiApi::can_handle(const char* path, int length, const char** /*pchild*/)
75 { 80 {
76 - return !memcmp("/api", path, length); 81 + return srs_path_equals("/api", path, length);
77 } 82 }
78 83
79 -int SrsApiApi::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/) 84 +int SrsApiApi::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
80 { 85 {
81 - if (req->method() == HTTP_OPTIONS) {  
82 - return res_options(skt);  
83 - } else {  
84 - std::string body = "hello, api";  
85 - return res_text(skt, body);  
86 - }  
87 -  
88 - return ERROR_SUCCESS; 86 + std::string body = "hello, api";
  87 + return res_text(skt, body);
89 } 88 }
90 89
91 SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler) 90 SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
@@ -147,25 +146,31 @@ int SrsHttpApi::do_cycle() @@ -147,25 +146,31 @@ int SrsHttpApi::do_cycle()
147 int SrsHttpApi::process_request(SrsSocket* skt, SrsHttpMessage* req) 146 int SrsHttpApi::process_request(SrsSocket* skt, SrsHttpMessage* req)
148 { 147 {
149 int ret = ERROR_SUCCESS; 148 int ret = ERROR_SUCCESS;
  149 +
  150 + // parse uri to schema/server:port/path?query
  151 + if ((ret = req->parse_uri()) != ERROR_SUCCESS) {
  152 + return ret;
  153 + }
150 154
151 // TODO: maybe need to parse the url. 155 // TODO: maybe need to parse the url.
152 - std::string uri = req->url(); 156 + std::string url = req->path();
153 157
154 - int length = 0;  
155 - const char* start = NULL;  
156 - SrsHttpHandler* p = NULL;  
157 - if ((ret = handler->best_match(uri.data(), uri.length(), &p, &start, &length)) != ERROR_SUCCESS) { 158 + SrsHttpHandlerMatch* p = NULL;
  159 + if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) {
158 srs_warn("failed to find the best match handler for url. ret=%d", ret); 160 srs_warn("failed to find the best match handler for url. ret=%d", ret);
159 return ret; 161 return ret;
160 } 162 }
161 163
162 // if success, p and pstart should be valid. 164 // if success, p and pstart should be valid.
163 srs_assert(p); 165 srs_assert(p);
164 - srs_assert(start);  
165 - srs_assert(length <= (int)uri.length()); 166 + srs_assert(p->handler);
  167 + srs_assert(p->matched_url.length() <= url.length());
  168 + srs_info("best match handler, matched_url=%s", p->matched_url.c_str());
  169 +
  170 + req->set_match(p);
166 171
167 // use handler to process request. 172 // use handler to process request.
168 - if ((ret = p->process_request(skt, req, start, length)) != ERROR_SUCCESS) { 173 + if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) {
169 srs_warn("handler failed to process http request. ret=%d", ret); 174 srs_warn("handler failed to process http request. ret=%d", ret);
170 return ret; 175 return ret;
171 } 176 }
@@ -48,8 +48,8 @@ public: @@ -48,8 +48,8 @@ public:
48 SrsApiRoot(); 48 SrsApiRoot();
49 virtual ~SrsApiRoot(); 49 virtual ~SrsApiRoot();
50 public: 50 public:
51 - virtual bool can_handle(const char* path, int length, const char** pnext_path);  
52 - virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length); 51 + virtual bool can_handle(const char* path, int length, const char** pchild);
  52 + virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
53 }; 53 };
54 54
55 class SrsApiApi : public SrsHttpHandler 55 class SrsApiApi : public SrsHttpHandler
@@ -58,8 +58,8 @@ public: @@ -58,8 +58,8 @@ public:
58 SrsApiApi(); 58 SrsApiApi();
59 virtual ~SrsApiApi(); 59 virtual ~SrsApiApi();
60 public: 60 public:
61 - virtual bool can_handle(const char* path, int length, const char** pnext_path);  
62 - virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length); 61 + virtual bool can_handle(const char* path, int length, const char** pchild);
  62 + virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
63 }; 63 };
64 64
65 class SrsHttpApi : public SrsConnection 65 class SrsHttpApi : public SrsConnection
@@ -35,6 +35,7 @@ using namespace std; @@ -35,6 +35,7 @@ using namespace std;
35 #include <srs_kernel_log.hpp> 35 #include <srs_kernel_log.hpp>
36 #include <srs_app_socket.hpp> 36 #include <srs_app_socket.hpp>
37 #include <srs_app_http.hpp> 37 #include <srs_app_http.hpp>
  38 +#include <srs_app_json.hpp>
38 39
39 #define SRS_HTTP_RESPONSE_OK "0" 40 #define SRS_HTTP_RESPONSE_OK "0"
40 41
@@ -202,32 +203,14 @@ int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, Srs @@ -202,32 +203,14 @@ int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, Srs
202 } 203 }
203 */ 204 */
204 std::stringstream ss; 205 std::stringstream ss;
205 - ss << "{"  
206 - // action  
207 - << '"' << "action" << '"' << ':'  
208 - << '"' << "on_connect" << '"'  
209 - << ','  
210 - // client_id  
211 - << '"' << "client_id" << '"' << ':'  
212 - << std::dec << client_id  
213 - << ','  
214 - // ip  
215 - << '"' << "ip" << '"' << ':'  
216 - << '"' << ip << '"'  
217 - << ','  
218 - // vhost  
219 - << '"' << "vhost" << '"' << ':'  
220 - << '"' << req->vhost << '"'  
221 - << ','  
222 - // app  
223 - << '"' << "app" << '"' << ':'  
224 - << '"' << req->app << '"'  
225 - << ','  
226 - // pageUrl  
227 - << '"' << "pageUrl" << '"' << ':'  
228 - << '"' << req->pageUrl << '"'  
229 - //<< ','  
230 - << "}"; 206 + ss << JOBJECT_START
  207 + << JFIELD_STR("action", "on_connect") << JFIELD_CONT
  208 + << JFIELD_ORG("client_id", client_id) << JFIELD_CONT
  209 + << JFIELD_STR("ip", ip) << JFIELD_CONT
  210 + << JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
  211 + << JFIELD_STR("app", req->app) << JFIELD_CONT
  212 + << JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
  213 + << JOBJECT_END;
231 std::string data = ss.str(); 214 std::string data = ss.str();
232 std::string res; 215 std::string res;
233 216
@@ -273,28 +256,14 @@ void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsR @@ -273,28 +256,14 @@ void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsR
273 } 256 }
274 */ 257 */
275 std::stringstream ss; 258 std::stringstream ss;
276 - ss << "{"  
277 - // action  
278 - << '"' << "action" << '"' << ':'  
279 - << '"' << "on_close" << '"'  
280 - << ','  
281 - // client_id  
282 - << '"' << "client_id" << '"' << ':'  
283 - << std::dec << client_id  
284 - << ','  
285 - // ip  
286 - << '"' << "ip" << '"' << ':'  
287 - << '"' << ip << '"'  
288 - << ','  
289 - // vhost  
290 - << '"' << "vhost" << '"' << ':'  
291 - << '"' << req->vhost << '"'  
292 - << ','  
293 - // app  
294 - << '"' << "app" << '"' << ':'  
295 - << '"' << req->app << '"'  
296 - //<< ','  
297 - << "}"; 259 + ss << JOBJECT_START
  260 + << JFIELD_STR("action", "on_close") << JFIELD_CONT
  261 + << JFIELD_ORG("client_id", client_id) << JFIELD_CONT
  262 + << JFIELD_STR("ip", ip) << JFIELD_CONT
  263 + << JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
  264 + << JFIELD_STR("app", req->app) << JFIELD_CONT
  265 + << JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
  266 + << JOBJECT_END;
298 std::string data = ss.str(); 267 std::string data = ss.str();
299 std::string res; 268 std::string res;
300 269
@@ -340,32 +309,15 @@ int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, Srs @@ -340,32 +309,15 @@ int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, Srs
340 } 309 }
341 */ 310 */
342 std::stringstream ss; 311 std::stringstream ss;
343 - ss << "{"  
344 - // action  
345 - << '"' << "action" << '"' << ':'  
346 - << '"' << "on_publish" << '"'  
347 - << ','  
348 - // client_id  
349 - << '"' << "client_id" << '"' << ':'  
350 - << std::dec << client_id  
351 - << ','  
352 - // ip  
353 - << '"' << "ip" << '"' << ':'  
354 - << '"' << ip << '"'  
355 - << ','  
356 - // vhost  
357 - << '"' << "vhost" << '"' << ':'  
358 - << '"' << req->vhost << '"'  
359 - << ','  
360 - // app  
361 - << '"' << "app" << '"' << ':'  
362 - << '"' << req->app << '"'  
363 - << ','  
364 - // stream  
365 - << '"' << "stream" << '"' << ':'  
366 - << '"' << req->stream << '"'  
367 - //<< ','  
368 - << "}"; 312 + ss << JOBJECT_START
  313 + << JFIELD_STR("action", "on_publish") << JFIELD_CONT
  314 + << JFIELD_ORG("client_id", client_id) << JFIELD_CONT
  315 + << JFIELD_STR("ip", ip) << JFIELD_CONT
  316 + << JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
  317 + << JFIELD_STR("app", req->app) << JFIELD_CONT
  318 + << JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
  319 + << JFIELD_STR("stream", req->stream) << JFIELD_CONT
  320 + << JOBJECT_END;
369 std::string data = ss.str(); 321 std::string data = ss.str();
370 std::string res; 322 std::string res;
371 323
@@ -411,32 +363,15 @@ void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, @@ -411,32 +363,15 @@ void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip,
411 } 363 }
412 */ 364 */
413 std::stringstream ss; 365 std::stringstream ss;
414 - ss << "{"  
415 - // action  
416 - << '"' << "action" << '"' << ':'  
417 - << '"' << "on_unpublish" << '"'  
418 - << ','  
419 - // client_id  
420 - << '"' << "client_id" << '"' << ':'  
421 - << std::dec << client_id  
422 - << ','  
423 - // ip  
424 - << '"' << "ip" << '"' << ':'  
425 - << '"' << ip << '"'  
426 - << ','  
427 - // vhost  
428 - << '"' << "vhost" << '"' << ':'  
429 - << '"' << req->vhost << '"'  
430 - << ','  
431 - // app  
432 - << '"' << "app" << '"' << ':'  
433 - << '"' << req->app << '"'  
434 - << ','  
435 - // stream  
436 - << '"' << "stream" << '"' << ':'  
437 - << '"' << req->stream << '"'  
438 - //<< ','  
439 - << "}"; 366 + ss << JOBJECT_START
  367 + << JFIELD_STR("action", "on_unpublish") << JFIELD_CONT
  368 + << JFIELD_ORG("client_id", client_id) << JFIELD_CONT
  369 + << JFIELD_STR("ip", ip) << JFIELD_CONT
  370 + << JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
  371 + << JFIELD_STR("app", req->app) << JFIELD_CONT
  372 + << JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
  373 + << JFIELD_STR("stream", req->stream) << JFIELD_CONT
  374 + << JOBJECT_END;
440 std::string data = ss.str(); 375 std::string data = ss.str();
441 std::string res; 376 std::string res;
442 377
@@ -482,32 +417,15 @@ int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsReq @@ -482,32 +417,15 @@ int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsReq
482 } 417 }
483 */ 418 */
484 std::stringstream ss; 419 std::stringstream ss;
485 - ss << "{"  
486 - // action  
487 - << '"' << "action" << '"' << ':'  
488 - << '"' << "on_play" << '"'  
489 - << ','  
490 - // client_id  
491 - << '"' << "client_id" << '"' << ':'  
492 - << std::dec << client_id  
493 - << ','  
494 - // ip  
495 - << '"' << "ip" << '"' << ':'  
496 - << '"' << ip << '"'  
497 - << ','  
498 - // vhost  
499 - << '"' << "vhost" << '"' << ':'  
500 - << '"' << req->vhost << '"'  
501 - << ','  
502 - // app  
503 - << '"' << "app" << '"' << ':'  
504 - << '"' << req->app << '"'  
505 - << ','  
506 - // stream  
507 - << '"' << "stream" << '"' << ':'  
508 - << '"' << req->stream << '"'  
509 - //<< ','  
510 - << "}"; 420 + ss << JOBJECT_START
  421 + << JFIELD_STR("action", "on_play") << JFIELD_CONT
  422 + << JFIELD_ORG("client_id", client_id) << JFIELD_CONT
  423 + << JFIELD_STR("ip", ip) << JFIELD_CONT
  424 + << JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
  425 + << JFIELD_STR("app", req->app) << JFIELD_CONT
  426 + << JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
  427 + << JFIELD_STR("stream", req->stream) << JFIELD_CONT
  428 + << JOBJECT_END;
511 std::string data = ss.str(); 429 std::string data = ss.str();
512 std::string res; 430 std::string res;
513 431
@@ -553,32 +471,15 @@ void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRe @@ -553,32 +471,15 @@ void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRe
553 } 471 }
554 */ 472 */
555 std::stringstream ss; 473 std::stringstream ss;
556 - ss << "{"  
557 - // action  
558 - << '"' << "action" << '"' << ':'  
559 - << '"' << "on_stop" << '"'  
560 - << ','  
561 - // client_id  
562 - << '"' << "client_id" << '"' << ':'  
563 - << std::dec << client_id  
564 - << ','  
565 - // ip  
566 - << '"' << "ip" << '"' << ':'  
567 - << '"' << ip << '"'  
568 - << ','  
569 - // vhost  
570 - << '"' << "vhost" << '"' << ':'  
571 - << '"' << req->vhost << '"'  
572 - << ','  
573 - // app  
574 - << '"' << "app" << '"' << ':'  
575 - << '"' << req->app << '"'  
576 - << ','  
577 - // stream  
578 - << '"' << "stream" << '"' << ':'  
579 - << '"' << req->stream << '"'  
580 - //<< ','  
581 - << "}"; 474 + ss << JOBJECT_START
  475 + << JFIELD_STR("action", "on_stop") << JFIELD_CONT
  476 + << JFIELD_ORG("client_id", client_id) << JFIELD_CONT
  477 + << JFIELD_STR("ip", ip) << JFIELD_CONT
  478 + << JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
  479 + << JFIELD_STR("app", req->app) << JFIELD_CONT
  480 + << JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
  481 + << JFIELD_STR("stream", req->stream) << JFIELD_CONT
  482 + << JOBJECT_END;
582 std::string data = ss.str(); 483 std::string data = ss.str();
583 std::string res; 484 std::string res;
584 485
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_app_json.hpp>
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_APP_JSON_HPP
  25 +#define SRS_APP_JSON_HPP
  26 +
  27 +/*
  28 +#include <srs_app_json.hpp>
  29 +*/
  30 +#include <srs_core.hpp>
  31 +
  32 +// json encode macros
  33 +#define JOBJECT_START "{"
  34 +#define JFIELD_STR(k, v) "\"" << k << "\":\"" << v << "\""
  35 +#define JFIELD_ORG(k, v) "\"" << k << "\":" << std::dec << v
  36 +#define JFIELD_ERROR(ret) "\"" << "code" << "\":" << ret
  37 +#define JFIELD_CONT ","
  38 +#define JOBJECT_END "}"
  39 +
  40 +#endif
@@ -61,6 +61,8 @@ file @@ -61,6 +61,8 @@ file
61 ..\app\srs_app_http_conn.cpp, 61 ..\app\srs_app_http_conn.cpp,
62 ..\app\srs_app_http_hooks.hpp, 62 ..\app\srs_app_http_hooks.hpp,
63 ..\app\srs_app_http_hooks.cpp, 63 ..\app\srs_app_http_hooks.cpp,
  64 + ..\app\srs_app_json.hpp,
  65 + ..\app\srs_app_json.cpp,
64 ..\app\srs_app_log.hpp, 66 ..\app\srs_app_log.hpp,
65 ..\app\srs_app_log.cpp, 67 ..\app\srs_app_log.cpp,
66 ..\app\srs_app_refer.hpp, 68 ..\app\srs_app_refer.hpp,