mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 11:51:57 +00:00
implements basic http response framework
This commit is contained in:
parent
341b5151d9
commit
bfa07465f0
4 changed files with 143 additions and 41 deletions
|
@ -59,7 +59,7 @@ int SrsHttpHandler::initialize()
|
||||||
return ret;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -86,20 +86,23 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
|
||||||
}
|
}
|
||||||
|
|
||||||
// whether the handler can handler the node.
|
// whether the handler can handler the node.
|
||||||
int node_size = p - path;
|
const char* pnext = p;
|
||||||
if (!can_handle(path, node_size)) {
|
if (!can_handle(path, p - path, &pnext)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save current handler, it's ok for current handler atleast.
|
||||||
*phandler = this;
|
*phandler = this;
|
||||||
*pstart = path;
|
*pstart = path;
|
||||||
*plength = node_size;
|
*plength = p - path;
|
||||||
|
|
||||||
|
// find the best matched child handler.
|
||||||
std::vector<SrsHttpHandler*>::iterator it;
|
std::vector<SrsHttpHandler*>::iterator it;
|
||||||
for (it = handlers.begin(); it != handlers.end(); ++it) {
|
for (it = handlers.begin(); it != handlers.end(); ++it) {
|
||||||
SrsHttpHandler* handler = *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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +119,76 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
|
||||||
return ret;
|
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()
|
SrsHttpHandler* SrsHttpHandler::create_http_api()
|
||||||
{
|
{
|
||||||
return new SrsApiRoot();
|
return new SrsApiRoot();
|
||||||
|
|
|
@ -33,6 +33,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <http_parser.h>
|
#include <http_parser.h>
|
||||||
|
|
||||||
|
@ -89,8 +90,9 @@ public:
|
||||||
virtual int initialize();
|
virtual int initialize();
|
||||||
/**
|
/**
|
||||||
* whether current handler can handle the specified path.
|
* 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.
|
* use the handler to process the request.
|
||||||
*/
|
*/
|
||||||
|
@ -100,6 +102,17 @@ public:
|
||||||
* find the best matched handler
|
* find the best matched handler
|
||||||
*/
|
*/
|
||||||
virtual int best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength);
|
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:
|
public:
|
||||||
/**
|
/**
|
||||||
* create http api resource handler.
|
* create http api resource handler.
|
||||||
|
|
|
@ -36,21 +36,56 @@ using namespace std;
|
||||||
|
|
||||||
SrsApiRoot::SrsApiRoot()
|
SrsApiRoot::SrsApiRoot()
|
||||||
{
|
{
|
||||||
|
handlers.push_back(new SrsApiApi());
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsApiRoot::~SrsApiRoot()
|
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;
|
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;
|
if (req->method() == HTTP_OPTIONS) {
|
||||||
return ret;
|
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)
|
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;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,17 @@ public:
|
||||||
SrsApiRoot();
|
SrsApiRoot();
|
||||||
virtual ~SrsApiRoot();
|
virtual ~SrsApiRoot();
|
||||||
public:
|
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);
|
virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue