winlin

implements basic http response framework

... ... @@ -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<SrsHttpHandler*>::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();
... ...
... ... @@ -33,6 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <string>
#include <vector>
#include <sstream>
#include <http_parser.h>
... ... @@ -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.
*/
... ... @@ -101,6 +103,17 @@ public:
*/
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.
*/
... ...
... ... @@ -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;
}
... ...
... ... @@ -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);
};
... ...