winlin

implements basic http response framework

@@ -59,7 +59,7 @@ int SrsHttpHandler::initialize() @@ -59,7 +59,7 @@ int SrsHttpHandler::initialize()
59 return ret; 59 return ret;
60 } 60 }
61 61
62 -bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/) 62 +bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/, const char** /*pnext_path*/)
63 { 63 {
64 return false; 64 return false;
65 } 65 }
@@ -86,20 +86,23 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph @@ -86,20 +86,23 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
86 } 86 }
87 87
88 // whether the handler can handler the node. 88 // whether the handler can handler the node.
89 - int node_size = p - path;  
90 - if (!can_handle(path, node_size)) { 89 + const char* pnext = p;
  90 + if (!can_handle(path, p - path, &pnext)) {
91 break; 91 break;
92 } 92 }
93 93
  94 + // save current handler, it's ok for current handler atleast.
94 *phandler = this; 95 *phandler = this;
95 *pstart = path; 96 *pstart = path;
96 - *plength = node_size; 97 + *plength = p - path;
97 98
  99 + // find the best matched child handler.
98 std::vector<SrsHttpHandler*>::iterator it; 100 std::vector<SrsHttpHandler*>::iterator it;
99 for (it = handlers.begin(); it != handlers.end(); ++it) { 101 for (it = handlers.begin(); it != handlers.end(); ++it) {
100 SrsHttpHandler* handler = *it; 102 SrsHttpHandler* handler = *it;
101 - // matched, donot search.  
102 - if (handler->best_match(p, length - node_size, phandler, pstart, plength) == ERROR_SUCCESS) { 103 +
  104 + // matched, donot search more.
  105 + if (handler->best_match(pnext, length - (pnext - path), phandler, pstart, plength) == ERROR_SUCCESS) {
103 break; 106 break;
104 } 107 }
105 } 108 }
@@ -116,6 +119,76 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph @@ -116,6 +119,76 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
116 return ret; 119 return ret;
117 } 120 }
118 121
  122 +SrsHttpHandler* SrsHttpHandler::res_status_line(std::stringstream& ss)
  123 +{
  124 + ss << "HTTP/1.1 200 OK " << __CRLF
  125 + << "Server: SRS/"RTMP_SIG_SRS_VERSION"" << __CRLF;
  126 + return this;
  127 +}
  128 +
  129 +SrsHttpHandler* SrsHttpHandler::res_content_type(std::stringstream& ss)
  130 +{
  131 + ss << "Content-Type: text/html;charset=utf-8" << __CRLF
  132 + << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __CRLF;
  133 + return this;
  134 +}
  135 +
  136 +SrsHttpHandler* SrsHttpHandler::res_content_length(std::stringstream& ss, int64_t length)
  137 +{
  138 + ss << "Content-Length: "<< length << __CRLF;
  139 + return this;
  140 +}
  141 +
  142 +SrsHttpHandler* SrsHttpHandler::res_enable_crossdomain(std::stringstream& ss)
  143 +{
  144 + ss << "Access-Control-Allow-Origin: *" << __CRLF
  145 + << "Access-Control-Allow-Methods: "
  146 + << "GET, POST, HEAD, PUT, DELETE" << __CRLF
  147 + << "Access-Control-Allow-Headers: "
  148 + << "Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type" << __CRLF;
  149 + return this;
  150 +}
  151 +
  152 +SrsHttpHandler* SrsHttpHandler::res_header_eof(std::stringstream& ss)
  153 +{
  154 + ss << __CRLF;
  155 + return this;
  156 +}
  157 +
  158 +SrsHttpHandler* SrsHttpHandler::res_body(std::stringstream& ss, std::string body)
  159 +{
  160 + ss << body;
  161 + return this;
  162 +}
  163 +
  164 +int SrsHttpHandler::res_flush(SrsSocket* skt, std::stringstream& ss)
  165 +{
  166 + return skt->write(ss.str().c_str(), ss.str().length(), NULL);
  167 +}
  168 +
  169 +int SrsHttpHandler::res_options(SrsSocket* skt)
  170 +{
  171 + std::stringstream ss;
  172 +
  173 + res_status_line(ss)->res_content_type(ss)
  174 + ->res_content_length(ss, 0)->res_enable_crossdomain(ss)
  175 + ->res_header_eof(ss);
  176 +
  177 + return res_flush(skt, ss);
  178 +}
  179 +
  180 +int SrsHttpHandler::res_text(SrsSocket* skt, std::string body)
  181 +{
  182 + std::stringstream ss;
  183 +
  184 + res_status_line(ss)->res_content_type(ss)
  185 + ->res_content_length(ss, (int)body.length())->res_enable_crossdomain(ss)
  186 + ->res_header_eof(ss)
  187 + ->res_body(ss, body);
  188 +
  189 + return res_flush(skt, ss);
  190 +}
  191 +
119 SrsHttpHandler* SrsHttpHandler::create_http_api() 192 SrsHttpHandler* SrsHttpHandler::create_http_api()
120 { 193 {
121 return new SrsApiRoot(); 194 return new SrsApiRoot();
@@ -33,6 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -33,6 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 33
34 #include <string> 34 #include <string>
35 #include <vector> 35 #include <vector>
  36 +#include <sstream>
36 37
37 #include <http_parser.h> 38 #include <http_parser.h>
38 39
@@ -89,8 +90,9 @@ public: @@ -89,8 +90,9 @@ public:
89 virtual int initialize(); 90 virtual int initialize();
90 /** 91 /**
91 * whether current handler can handle the specified path. 92 * whether current handler can handle the specified path.
  93 + * @pnext_path set the next path, if needed.
92 */ 94 */
93 - virtual bool can_handle(const char* path, int length); 95 + virtual bool can_handle(const char* path, int length, const char** pnext_path);
94 /** 96 /**
95 * use the handler to process the request. 97 * use the handler to process the request.
96 */ 98 */
@@ -101,6 +103,17 @@ public: @@ -101,6 +103,17 @@ public:
101 */ 103 */
102 virtual int best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength); 104 virtual int best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength);
103 public: 105 public:
  106 + virtual SrsHttpHandler* res_status_line(std::stringstream& ss);
  107 + virtual SrsHttpHandler* res_content_type(std::stringstream& ss);
  108 + virtual SrsHttpHandler* res_content_length(std::stringstream& ss, int64_t length);
  109 + virtual SrsHttpHandler* res_enable_crossdomain(std::stringstream& ss);
  110 + virtual SrsHttpHandler* res_header_eof(std::stringstream& ss);
  111 + virtual SrsHttpHandler* res_body(std::stringstream& ss, std::string body);
  112 + virtual int res_flush(SrsSocket* skt, std::stringstream& ss);
  113 +public:
  114 + virtual int res_options(SrsSocket* skt);
  115 + virtual int res_text(SrsSocket* skt, std::string body);
  116 +public:
104 /** 117 /**
105 * create http api resource handler. 118 * create http api resource handler.
106 */ 119 */
@@ -36,21 +36,56 @@ using namespace std; @@ -36,21 +36,56 @@ using namespace std;
36 36
37 SrsApiRoot::SrsApiRoot() 37 SrsApiRoot::SrsApiRoot()
38 { 38 {
  39 + handlers.push_back(new SrsApiApi());
39 } 40 }
40 41
41 SrsApiRoot::~SrsApiRoot() 42 SrsApiRoot::~SrsApiRoot()
42 { 43 {
43 } 44 }
44 45
45 -bool SrsApiRoot::can_handle(const char* /*path*/, int /*length*/) 46 +bool SrsApiRoot::can_handle(const char* path, int length, const char** pnext_path)
46 { 47 {
  48 + // reset the next path for child to parse.
  49 + *pnext_path = path;
  50 +
47 return true; 51 return true;
48 } 52 }
49 53
50 -int SrsApiRoot::process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/, const char* /*path*/, int /*length*/) 54 +int SrsApiRoot::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/)
51 { 55 {
52 - int ret = ERROR_SUCCESS;  
53 - return ret; 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;
  64 +}
  65 +
  66 +SrsApiApi::SrsApiApi()
  67 +{
  68 +}
  69 +
  70 +SrsApiApi::~SrsApiApi()
  71 +{
  72 +}
  73 +
  74 +bool SrsApiApi::can_handle(const char* path, int length, const char** /*pnext_path*/)
  75 +{
  76 + return !memcmp("/api", path, length);
  77 +}
  78 +
  79 +int SrsApiApi::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/)
  80 +{
  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;
54 } 89 }
55 90
56 SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler) 91 SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
@@ -135,35 +170,6 @@ int SrsHttpApi::process_request(SrsSocket* skt, SrsHttpMessage* req) @@ -135,35 +170,6 @@ int SrsHttpApi::process_request(SrsSocket* skt, SrsHttpMessage* req)
135 return ret; 170 return ret;
136 } 171 }
137 172
138 - if (req->method() == HTTP_OPTIONS) {  
139 - char data[] = "HTTP/1.1 200 OK" __CRLF  
140 - "Content-Length: 0"__CRLF  
141 - "Server: SRS/"RTMP_SIG_SRS_VERSION""__CRLF  
142 - "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT"__CRLF  
143 - "Access-Control-Allow-Origin: *"__CRLF  
144 - "Access-Control-Allow-Methods: GET, POST, HEAD, PUT, DELETE"__CRLF  
145 - "Access-Control-Allow-Headers: Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type"__CRLF  
146 - "Content-Type: text/html;charset=utf-8"__CRLFCRLF  
147 - "";  
148 - return skt->write(data, sizeof(data), NULL);  
149 - } else {  
150 - std::string tilte = "SRS/"RTMP_SIG_SRS_VERSION;  
151 - tilte += " hello http/1.1 api~\n";  
152 -  
153 - std::stringstream ss;  
154 - ss << "HTTP/1.1 200 OK " << __CRLF  
155 - << "Content-Length: "<< tilte.length() + req->body_size() << __CRLF  
156 - << "Server: SRS/"RTMP_SIG_SRS_VERSION"" << __CRLF  
157 - << "Allow: DELETE, GET, HEAD, OPTIONS, POST, PUT" << __CRLF  
158 - << "Access-Control-Allow-Origin: *" << __CRLF  
159 - << "Access-Control-Allow-Methods: GET, POST, HEAD, PUT, DELETE" << __CRLF  
160 - << "Access-Control-Allow-Headers: Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type" << __CRLF  
161 - << "Content-Type: text/html;charset=utf-8" << __CRLFCRLF  
162 - << tilte << req->body().c_str()  
163 - << "";  
164 - return skt->write(ss.str().c_str(), ss.str().length(), NULL);  
165 - }  
166 -  
167 return ret; 173 return ret;
168 } 174 }
169 175
@@ -48,7 +48,17 @@ public: @@ -48,7 +48,17 @@ 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); 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);
  53 +};
  54 +
  55 +class SrsApiApi : public SrsHttpHandler
  56 +{
  57 +public:
  58 + SrsApiApi();
  59 + virtual ~SrsApiApi();
  60 +public:
  61 + 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); 62 virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length);
53 }; 63 };
54 64