1
0
Fork 0
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:
winlin 2014-04-01 14:28:19 +08:00
parent 51c1615173
commit 6ca9b774c1
5 changed files with 145 additions and 46 deletions

View file

@ -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

View file

@ -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;
} }

View file

@ -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);

View file

@ -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);
} }

View file

@ -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);
}; };