mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
support http methods, support js crossdomain request
This commit is contained in:
parent
51c1615173
commit
6ca9b774c1
5 changed files with 145 additions and 46 deletions
|
@ -46,7 +46,8 @@ namespace srs
|
||||||
// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
|
// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
|
||||||
// protocol elements except the entity-body (see appendix 19.3 for
|
// protocol elements except the entity-body (see appendix 19.3 for
|
||||||
// tolerant applications).
|
// tolerant applications).
|
||||||
#define __CRLF __CR""__LF // 0x0D0A
|
#define __CRLF "\r\n" // 0x0D0A
|
||||||
|
#define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SRS_HTTP_CALLBACK
|
#ifdef SRS_HTTP_CALLBACK
|
||||||
|
|
|
@ -23,22 +23,52 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <srs_app_http_conn.hpp>
|
#include <srs_app_http_conn.hpp>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_kernel_log.hpp>
|
#include <srs_kernel_log.hpp>
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
#include <srs_app_socket.hpp>
|
#include <srs_app_socket.hpp>
|
||||||
|
#include <srs_app_http.hpp>
|
||||||
|
#include <srs_kernel_buffer.hpp>
|
||||||
|
|
||||||
#define SRS_HTTP_HEADER_BUFFER 1024
|
#define SRS_HTTP_HEADER_BUFFER 1024
|
||||||
|
|
||||||
|
SrsHttpRequest::SrsHttpRequest()
|
||||||
|
{
|
||||||
|
body = new SrsBuffer();
|
||||||
|
state = SrsHttpParseStateInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsHttpRequest::~SrsHttpRequest()
|
||||||
|
{
|
||||||
|
srs_freep(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsHttpRequest::reset()
|
||||||
|
{
|
||||||
|
state = SrsHttpParseStateInit;
|
||||||
|
body->clear();
|
||||||
|
url = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsHttpRequest::is_complete()
|
||||||
|
{
|
||||||
|
return state == SrsHttpParseStateComplete;
|
||||||
|
}
|
||||||
|
|
||||||
SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd)
|
SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd)
|
||||||
: SrsConnection(srs_server, client_stfd)
|
: SrsConnection(srs_server, client_stfd)
|
||||||
{
|
{
|
||||||
|
req = new SrsHttpRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHttpConn::~SrsHttpConn()
|
SrsHttpConn::~SrsHttpConn()
|
||||||
{
|
{
|
||||||
|
srs_freep(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::do_cycle()
|
int SrsHttpConn::do_cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -69,7 +99,7 @@ int SrsHttpConn::do_cycle()
|
||||||
SrsSocket skt(stfd);
|
SrsSocket skt(stfd);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((ret = process_request(&skt, &parser, &settings)) != ERROR_SUCCESS) {
|
if ((ret = parse_request(&skt, &parser, &settings)) != ERROR_SUCCESS) {
|
||||||
if (!srs_is_client_gracefully_close(ret)) {
|
if (!srs_is_client_gracefully_close(ret)) {
|
||||||
srs_error("http client cycle failed. ret=%d", ret);
|
srs_error("http client cycle failed. ret=%d", ret);
|
||||||
}
|
}
|
||||||
|
@ -80,12 +110,12 @@ int SrsHttpConn::do_cycle()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::process_request(SrsSocket* skt, http_parser* parser, http_parser_settings* settings)
|
int SrsHttpConn::parse_request(SrsSocket* skt, http_parser* parser, http_parser_settings* settings)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// reset response header.
|
// reset response header.
|
||||||
http_header = NULL;
|
req->reset();
|
||||||
|
|
||||||
// parser header.
|
// parser header.
|
||||||
char buf[SRS_HTTP_HEADER_BUFFER];
|
char buf[SRS_HTTP_HEADER_BUFFER];
|
||||||
|
@ -102,13 +132,11 @@ int SrsHttpConn::process_request(SrsSocket* skt, http_parser* parser, http_parse
|
||||||
srs_info("read_size=%d, nparsed=%d", (int)nread, (int)nparsed);
|
srs_info("read_size=%d, nparsed=%d", (int)nread, (int)nparsed);
|
||||||
|
|
||||||
// check header size.
|
// check header size.
|
||||||
if (http_header) {
|
if (req->is_complete()) {
|
||||||
int nb_body = nread - nparsed;
|
srs_trace("http request parsed, method=%d, url=%s, content-length=%"PRId64"",
|
||||||
|
req->header.method, req->url.c_str(), req->header.content_length);
|
||||||
|
|
||||||
srs_info("http header parsed, size=%d, content-length=%"PRId64", nb_body=%d",
|
return process_request(skt);
|
||||||
http_header->nread, http_header->content_length, nb_body);
|
|
||||||
|
|
||||||
return complete_header(skt, http_header, buf + nparsed, nb_body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nparsed != nread) {
|
if (nparsed != nread) {
|
||||||
|
@ -121,17 +149,38 @@ int SrsHttpConn::process_request(SrsSocket* skt, http_parser* parser, http_parse
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::complete_header(SrsSocket* skt, http_parser* header, char* body, int nb_body)
|
int SrsHttpConn::process_request(SrsSocket* skt)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
char data[] = "HTTP/1.1 200 OK\r\n"
|
if (req->header.method == HTTP_OPTIONS) {
|
||||||
"Server: SRS/"RTMP_SIG_SRS_VERSION"\r\n"
|
char data[] = "HTTP/1.1 200 OK" __CRLF
|
||||||
"Content-Length: 15\r\n"
|
"Content-Length: 0"__CRLF
|
||||||
"Content-Type: text/html;charset=utf-8\r\n\r\n"
|
"Server: SRS/"RTMP_SIG_SRS_VERSION""__CRLF
|
||||||
"hello http/1.1~";
|
"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~\n";
|
||||||
|
|
||||||
skt->write(data, sizeof(data), NULL);
|
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->empty()? "":req->body->bytes())
|
||||||
|
<< "";
|
||||||
|
return skt->write(ss.str().c_str(), ss.str().length(), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -139,16 +188,19 @@ int SrsHttpConn::complete_header(SrsSocket* skt, http_parser* header, char* body
|
||||||
int SrsHttpConn::on_message_begin(http_parser* parser)
|
int SrsHttpConn::on_message_begin(http_parser* parser)
|
||||||
{
|
{
|
||||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||||
(void)obj;
|
obj->req->state = SrsHttpParseStateStart;
|
||||||
srs_trace("***MESSAGE BEGIN***");
|
|
||||||
|
srs_info("***MESSAGE BEGIN***");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::on_headers_complete(http_parser* parser)
|
int SrsHttpConn::on_headers_complete(http_parser* parser)
|
||||||
{
|
{
|
||||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||||
(void)obj;
|
memcpy(&obj->req->header, parser, sizeof(http_parser));
|
||||||
srs_trace("***HEADERS COMPLETE***");
|
|
||||||
|
srs_info("***HEADERS COMPLETE***");
|
||||||
|
|
||||||
// see http_parser.c:1570, return 1 to skip body.
|
// see http_parser.c:1570, return 1 to skip body.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -157,41 +209,48 @@ int SrsHttpConn::on_headers_complete(http_parser* parser)
|
||||||
int SrsHttpConn::on_message_complete(http_parser* parser)
|
int SrsHttpConn::on_message_complete(http_parser* parser)
|
||||||
{
|
{
|
||||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||||
srs_trace("***MESSAGE COMPLETE***\n");
|
|
||||||
|
|
||||||
// save the parser when header parse completed.
|
// save the parser when header parse completed.
|
||||||
obj->http_header = parser;
|
obj->req->state = SrsHttpParseStateComplete;
|
||||||
|
|
||||||
|
srs_info("***MESSAGE COMPLETE***\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::on_url(http_parser* parser, const char* at, size_t length)
|
int SrsHttpConn::on_url(http_parser* parser, const char* at, size_t length)
|
||||||
{
|
{
|
||||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||||
(void)obj;
|
|
||||||
srs_trace("Method: %d, Url: %.*s", parser->method, (int)length, at);
|
if (length > 0) {
|
||||||
|
obj->req->url.append(at, (int)length);
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_info("Method: %d, Url: %.*s", parser->method, (int)length, at);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::on_header_field(http_parser* parser, const char* at, size_t length)
|
int SrsHttpConn::on_header_field(http_parser* /*parser*/, const char* at, size_t length)
|
||||||
{
|
{
|
||||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
srs_info("Header field: %.*s", (int)length, at);
|
||||||
(void)obj;
|
|
||||||
srs_trace("Header field: %.*s", (int)length, at);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::on_header_value(http_parser* parser, const char* at, size_t length)
|
int SrsHttpConn::on_header_value(http_parser* /*parser*/, const char* at, size_t length)
|
||||||
{
|
{
|
||||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
srs_info("Header value: %.*s", (int)length, at);
|
||||||
(void)obj;
|
|
||||||
srs_trace("Header value: %.*s", (int)length, at);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpConn::on_body(http_parser* parser, const char* at, size_t length)
|
int SrsHttpConn::on_body(http_parser* parser, const char* at, size_t length)
|
||||||
{
|
{
|
||||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||||
(void)obj;
|
|
||||||
srs_trace("Body: %.*s", (int)length, at);
|
if (length > 0) {
|
||||||
|
obj->req->body->append(at, (int)length);
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_info("Body: %.*s", (int)length, at);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,19 +36,41 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <http_parser.h>
|
#include <http_parser.h>
|
||||||
|
|
||||||
class SrsSocket;
|
class SrsSocket;
|
||||||
|
class SrsBuffer;
|
||||||
|
|
||||||
|
enum SrsHttpParseState {
|
||||||
|
SrsHttpParseStateInit = 0,
|
||||||
|
SrsHttpParseStateStart,
|
||||||
|
SrsHttpParseStateComplete
|
||||||
|
};
|
||||||
|
|
||||||
|
class SrsHttpRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string url;
|
||||||
|
http_parser header;
|
||||||
|
SrsBuffer* body;
|
||||||
|
SrsHttpParseState state;
|
||||||
|
|
||||||
|
SrsHttpRequest();
|
||||||
|
virtual ~SrsHttpRequest();
|
||||||
|
|
||||||
|
virtual void reset();
|
||||||
|
virtual bool is_complete();
|
||||||
|
};
|
||||||
|
|
||||||
class SrsHttpConn : public SrsConnection
|
class SrsHttpConn : public SrsConnection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
http_parser* http_header;
|
SrsHttpRequest* req;
|
||||||
public:
|
public:
|
||||||
SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd);
|
SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||||
virtual ~SrsHttpConn();
|
virtual ~SrsHttpConn();
|
||||||
protected:
|
protected:
|
||||||
virtual int do_cycle();
|
virtual int do_cycle();
|
||||||
private:
|
private:
|
||||||
virtual int process_request(SrsSocket* skt, http_parser* parser, http_parser_settings* settings);
|
virtual int parse_request(SrsSocket* skt, http_parser* parser, http_parser_settings* settings);
|
||||||
virtual int complete_header(SrsSocket* skt, http_parser* header, char* body, int nb_body);
|
virtual int process_request(SrsSocket* skt);
|
||||||
private:
|
private:
|
||||||
static int on_message_begin(http_parser* parser);
|
static int on_message_begin(http_parser* parser);
|
||||||
static int on_headers_complete(http_parser* parser);
|
static int on_headers_complete(http_parser* parser);
|
||||||
|
|
|
@ -49,18 +49,34 @@ int SrsBuffer::size()
|
||||||
return (int)data.size();
|
return (int)data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsBuffer::empty()
|
||||||
|
{
|
||||||
|
return size() <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
char* SrsBuffer::bytes()
|
char* SrsBuffer::bytes()
|
||||||
{
|
{
|
||||||
return &data.at(0);
|
return &data.at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsBuffer::erase(int size)
|
void SrsBuffer::erase(int _size)
|
||||||
{
|
{
|
||||||
data.erase(data.begin(), data.begin() + size);
|
if (_size == size()) {
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.erase(data.begin(), data.begin() + _size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsBuffer::append(char* bytes, int size)
|
void SrsBuffer::clear()
|
||||||
{
|
{
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsBuffer::append(const char* bytes, int size)
|
||||||
|
{
|
||||||
|
srs_assert(size > 0);
|
||||||
data.insert(data.end(), bytes, bytes + size);
|
data.insert(data.end(), bytes, bytes + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,10 +59,11 @@ public:
|
||||||
virtual ~SrsBuffer();
|
virtual ~SrsBuffer();
|
||||||
public:
|
public:
|
||||||
virtual int size();
|
virtual int size();
|
||||||
|
virtual bool empty();
|
||||||
virtual char* bytes();
|
virtual char* bytes();
|
||||||
virtual void erase(int size);
|
virtual void erase(int size);
|
||||||
private:
|
virtual void clear();
|
||||||
virtual void append(char* bytes, int size);
|
virtual void append(const char* bytes, int size);
|
||||||
public:
|
public:
|
||||||
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
|
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue