winlin

support http methods, support js crossdomain request

... ... @@ -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,22 +23,52 @@ 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()
SrsHttpConn::~SrsHttpConn()
{
srs_freep(req);
}
int SrsHttpConn::do_cycle()
int SrsHttpConn::do_cycle()
{
int ret = ERROR_SUCCESS;
... ... @@ -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;
srs_info("http header parsed, size=%d, content-length=%"PRId64", nb_body=%d",
http_header->nread, http_header->content_length, nb_body);
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);
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)
{
if (_size == size()) {
clear();
return;
}
data.erase(data.begin(), data.begin() + _size);
}
void SrsBuffer::clear()
{
data.erase(data.begin(), data.begin() + size);
data.clear();
}
void SrsBuffer::append(char* bytes, int size)
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);
};
... ...