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
|
||||
// protocol elements except the entity-body (see appendix 19.3 for
|
||||
// tolerant applications).
|
||||
#define __CRLF __CR""__LF // 0x0D0A
|
||||
#define __CRLF "\r\n" // 0x0D0A
|
||||
#define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
|
||||
};
|
||||
|
||||
#ifdef SRS_HTTP_CALLBACK
|
||||
|
|
|
@ -23,19 +23,49 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <srs_app_http_conn.hpp>
|
||||
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_app_socket.hpp>
|
||||
#include <srs_app_http.hpp>
|
||||
#include <srs_kernel_buffer.hpp>
|
||||
|
||||
#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)
|
||||
: SrsConnection(srs_server, client_stfd)
|
||||
{
|
||||
req = new SrsHttpRequest();
|
||||
}
|
||||
|
||||
SrsHttpConn::~SrsHttpConn()
|
||||
{
|
||||
srs_freep(req);
|
||||
}
|
||||
|
||||
int SrsHttpConn::do_cycle()
|
||||
|
@ -69,7 +99,7 @@ int SrsHttpConn::do_cycle()
|
|||
SrsSocket skt(stfd);
|
||||
|
||||
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)) {
|
||||
srs_error("http client cycle failed. ret=%d", ret);
|
||||
}
|
||||
|
@ -80,12 +110,12 @@ int SrsHttpConn::do_cycle()
|
|||
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;
|
||||
|
||||
// reset response header.
|
||||
http_header = NULL;
|
||||
req->reset();
|
||||
|
||||
// parser header.
|
||||
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);
|
||||
|
||||
// check header size.
|
||||
if (http_header) {
|
||||
int nb_body = nread - nparsed;
|
||||
if (req->is_complete()) {
|
||||
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",
|
||||
http_header->nread, http_header->content_length, nb_body);
|
||||
|
||||
return complete_header(skt, http_header, buf + nparsed, nb_body);
|
||||
return process_request(skt);
|
||||
}
|
||||
|
||||
if (nparsed != nread) {
|
||||
|
@ -121,17 +149,38 @@ int SrsHttpConn::process_request(SrsSocket* skt, http_parser* parser, http_parse
|
|||
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;
|
||||
|
||||
char data[] = "HTTP/1.1 200 OK\r\n"
|
||||
"Server: SRS/"RTMP_SIG_SRS_VERSION"\r\n"
|
||||
"Content-Length: 15\r\n"
|
||||
"Content-Type: text/html;charset=utf-8\r\n\r\n"
|
||||
"hello http/1.1~";
|
||||
if (req->header.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~\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;
|
||||
}
|
||||
|
@ -139,16 +188,19 @@ int SrsHttpConn::complete_header(SrsSocket* skt, http_parser* header, char* body
|
|||
int SrsHttpConn::on_message_begin(http_parser* parser)
|
||||
{
|
||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||
(void)obj;
|
||||
srs_trace("***MESSAGE BEGIN***");
|
||||
obj->req->state = SrsHttpParseStateStart;
|
||||
|
||||
srs_info("***MESSAGE BEGIN***");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SrsHttpConn::on_headers_complete(http_parser* parser)
|
||||
{
|
||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||
(void)obj;
|
||||
srs_trace("***HEADERS COMPLETE***");
|
||||
memcpy(&obj->req->header, parser, sizeof(http_parser));
|
||||
|
||||
srs_info("***HEADERS COMPLETE***");
|
||||
|
||||
// see http_parser.c:1570, return 1 to skip body.
|
||||
return 0;
|
||||
|
@ -157,41 +209,48 @@ int SrsHttpConn::on_headers_complete(http_parser* parser)
|
|||
int SrsHttpConn::on_message_complete(http_parser* parser)
|
||||
{
|
||||
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
|
||||
srs_trace("***MESSAGE COMPLETE***\n");
|
||||
|
||||
// save the parser when header parse completed.
|
||||
obj->http_header = parser;
|
||||
obj->req->state = SrsHttpParseStateComplete;
|
||||
|
||||
srs_info("***MESSAGE COMPLETE***\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SrsHttpConn::on_url(http_parser* parser, const char* at, size_t length)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
(void)obj;
|
||||
srs_trace("Header field: %.*s", (int)length, at);
|
||||
srs_info("Header field: %.*s", (int)length, at);
|
||||
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;
|
||||
(void)obj;
|
||||
srs_trace("Header value: %.*s", (int)length, at);
|
||||
srs_info("Header value: %.*s", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SrsHttpConn::on_body(http_parser* parser, const char* at, size_t length)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -36,19 +36,41 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <http_parser.h>
|
||||
|
||||
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
|
||||
{
|
||||
private:
|
||||
http_parser* http_header;
|
||||
SrsHttpRequest* req;
|
||||
public:
|
||||
SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||
virtual ~SrsHttpConn();
|
||||
protected:
|
||||
virtual int do_cycle();
|
||||
private:
|
||||
virtual int process_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 parse_request(SrsSocket* skt, http_parser* parser, http_parser_settings* settings);
|
||||
virtual int process_request(SrsSocket* skt);
|
||||
private:
|
||||
static int on_message_begin(http_parser* parser);
|
||||
static int on_headers_complete(http_parser* parser);
|
||||
|
|
|
@ -49,18 +49,34 @@ int SrsBuffer::size()
|
|||
return (int)data.size();
|
||||
}
|
||||
|
||||
bool SrsBuffer::empty()
|
||||
{
|
||||
return size() <= 0;
|
||||
}
|
||||
|
||||
char* SrsBuffer::bytes()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,10 +59,11 @@ public:
|
|||
virtual ~SrsBuffer();
|
||||
public:
|
||||
virtual int size();
|
||||
virtual bool empty();
|
||||
virtual char* bytes();
|
||||
virtual void erase(int size);
|
||||
private:
|
||||
virtual void append(char* bytes, int size);
|
||||
virtual void clear();
|
||||
virtual void append(const char* bytes, int size);
|
||||
public:
|
||||
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue