refine the http url handler match. refine json encode

pull/133/head
winlin 11 years ago
parent bfa07465f0
commit a14267d2b4

2
trunk/configure vendored

@ -427,7 +427,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke
"srs_app_codec" "srs_app_refer" "srs_app_hls" "srs_app_forward" "srs_app_encoder"
"srs_app_http" "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log"
"srs_app_config" "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api"
"srs_app_http_conn" "srs_app_http_hooks")
"srs_app_http_conn" "srs_app_http_hooks" "srs_app_json")
APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
APP_OBJS="${MODULE_OBJS[@]}"
#

@ -39,6 +39,22 @@ using namespace std;
#define SRS_HTTP_HEADER_BUFFER 1024
bool srs_path_equals(const char* expect, const char* path, int nb_path)
{
int size = strlen(expect);
if (size != nb_path) {
return false;
}
return !memcmp(expect, path, size);
}
SrsHttpHandlerMatch::SrsHttpHandlerMatch()
{
handler = NULL;
}
SrsHttpHandler::SrsHttpHandler()
{
}
@ -59,21 +75,34 @@ int SrsHttpHandler::initialize()
return ret;
}
bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/, const char** /*pnext_path*/)
bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/, const char** /*pchild*/)
{
return false;
}
int SrsHttpHandler::process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/, const char* /*path*/, int /*length*/)
int SrsHttpHandler::process_request(SrsSocket* skt, SrsHttpMessage* req)
{
if (req->method() == HTTP_OPTIONS) {
return res_options(skt);
}
return do_process_request(skt, req);
}
int SrsHttpHandler::do_process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength)
int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch)
{
int ret = ERROR_SUCCESS;
SrsHttpHandler* handler = NULL;
const char* match_start = NULL;
int match_length = 0;
for (;;) {
// ensure cur is not NULL.
// ensure p not NULL and has bytes to parse.
@ -86,23 +115,23 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
}
// whether the handler can handler the node.
const char* pnext = p;
if (!can_handle(path, p - path, &pnext)) {
const char* pchild = p;
if (!can_handle(path, p - path, &pchild)) {
break;
}
// save current handler, it's ok for current handler atleast.
*phandler = this;
*pstart = path;
*plength = p - path;
handler = this;
match_start = path;
match_length = p - path;
// find the best matched child handler.
std::vector<SrsHttpHandler*>::iterator it;
for (it = handlers.begin(); it != handlers.end(); ++it) {
SrsHttpHandler* handler = *it;
SrsHttpHandler* h = *it;
// matched, donot search more.
if (handler->best_match(pnext, length - (pnext - path), phandler, pstart, plength) == ERROR_SUCCESS) {
if (h->best_match(pchild, length - (pchild - path), ppmatch) == ERROR_SUCCESS) {
break;
}
}
@ -111,11 +140,22 @@ int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** ph
break;
}
if (*phandler == NULL) {
// if already matched by child, return.
if (*ppmatch) {
return ret;
}
// not matched, error.
if (handler == NULL) {
ret = ERROR_HTTP_HANDLER_MATCH_URL;
return ret;
}
// matched by this handler.
*ppmatch = new SrsHttpHandlerMatch();
(*ppmatch)->handler = handler;
(*ppmatch)->matched_url.append(match_start, match_length);
return ret;
}
@ -133,6 +173,13 @@ SrsHttpHandler* SrsHttpHandler::res_content_type(std::stringstream& ss)
return this;
}
SrsHttpHandler* SrsHttpHandler::res_content_type_json(std::stringstream& ss)
{
ss << "Content-Type: application/json;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;
@ -189,6 +236,18 @@ int SrsHttpHandler::res_text(SrsSocket* skt, std::string body)
return res_flush(skt, ss);
}
int SrsHttpHandler::res_json(SrsSocket* skt, std::string json)
{
std::stringstream ss;
res_status_line(ss)->res_content_type_json(ss)
->res_content_length(ss, (int)json.length())->res_enable_crossdomain(ss)
->res_header_eof(ss)
->res_body(ss, json);
return res_flush(skt, ss);
}
SrsHttpHandler* SrsHttpHandler::create_http_api()
{
return new SrsApiRoot();
@ -204,11 +263,15 @@ SrsHttpMessage::SrsHttpMessage()
{
_body = new SrsBuffer();
_state = SrsHttpParseStateInit;
_uri = new SrsHttpUri();
_match = NULL;
}
SrsHttpMessage::~SrsHttpMessage()
{
srs_freep(_body);
srs_freep(_uri);
srs_freep(_match);
}
void SrsHttpMessage::reset()
@ -218,6 +281,11 @@ void SrsHttpMessage::reset()
_url = "";
}
int SrsHttpMessage::parse_uri()
{
return _uri->initialize(_url);
}
bool SrsHttpMessage::is_complete()
{
return _state == SrsHttpParseStateComplete;
@ -230,7 +298,17 @@ u_int8_t SrsHttpMessage::method()
string SrsHttpMessage::url()
{
return _url;
return _uri->get_url();
}
string SrsHttpMessage::path()
{
return _uri->get_path();
}
string SrsHttpMessage::query()
{
return _uri->get_query();
}
string SrsHttpMessage::body()
@ -254,6 +332,11 @@ int64_t SrsHttpMessage::content_length()
return _header.content_length;
}
SrsHttpHandlerMatch* SrsHttpMessage::match()
{
return _match;
}
void SrsHttpMessage::set_url(std::string url)
{
_url = url;
@ -269,6 +352,12 @@ void SrsHttpMessage::set_header(http_parser* header)
memcpy(&_header, header, sizeof(http_parser));
}
void SrsHttpMessage::set_match(SrsHttpHandlerMatch* match)
{
srs_freep(_match);
_match = match;
}
void SrsHttpMessage::append_body(const char* body, int length)
{
_body->append(body, length);
@ -489,22 +578,25 @@ int SrsHttpUri::initialize(std::string _url)
path = get_uri_field(url, &hp_u, UF_PATH);
srs_info("parse url %s success", purl);
query = get_uri_field(url, &hp_u, UF_QUERY);
srs_trace("parse query %s success", purl);
return ret;
}
const char* SrsHttpUri::get_url()
{
return url.c_str();
return url.data();
}
const char* SrsHttpUri::get_schema()
{
return schema.c_str();
return schema.data();
}
const char* SrsHttpUri::get_host()
{
return host.c_str();
return host.data();
}
int SrsHttpUri::get_port()
@ -514,7 +606,12 @@ int SrsHttpUri::get_port()
const char* SrsHttpUri::get_path()
{
return path.c_str();
return path.data();
}
const char* SrsHttpUri::get_query()
{
return path.data();
}
std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, http_parser_url_fields field)

@ -42,7 +42,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsBuffer;
class SrsRequest;
class SrsSocket;
class SrsHttpUri;
class SrsHttpMessage;
class SrsHttpHandler;
// http specification
// CR = <US-ASCII CR, carriage return (13)>
@ -62,6 +64,12 @@ class SrsHttpMessage;
// linux path seprator
#define __PATH_SEP '/'
// query string seprator
#define __QUERY_SEP '?'
// compare the path.
// full compare, extractly match.
extern bool srs_path_equals(const char* expect, const char* path, int nb_path);
// state of message
enum SrsHttpParseState {
@ -70,6 +78,18 @@ enum SrsHttpParseState {
SrsHttpParseStateComplete
};
/**
* the matched handler info.
*/
class SrsHttpHandlerMatch
{
public:
SrsHttpHandler* handler;
std::string matched_url;
public:
SrsHttpHandlerMatch();
};
/**
* resource handler for HTTP RESTful api.
*/
@ -90,21 +110,29 @@ public:
virtual int initialize();
/**
* whether current handler can handle the specified path.
* @pnext_path set the next path, if needed.
* @pchild set the next child path, if needed.
* for example, the root handler will reset pchild to path,
* to reparse the path use child handlers.
*/
virtual bool can_handle(const char* path, int length, const char** pnext_path);
virtual bool can_handle(const char* path, int length, const char** pchild);
/**
* use the handler to process the request.
* @remark sub classes should override the do_process_request.
*/
virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length);
virtual int process_request(SrsSocket* skt, SrsHttpMessage* req);
public:
/**
* 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, SrsHttpHandlerMatch** ppmatch);
// factory methods
protected:
virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
// response writer
public:
virtual SrsHttpHandler* res_status_line(std::stringstream& ss);
virtual SrsHttpHandler* res_content_type(std::stringstream& ss);
virtual SrsHttpHandler* res_content_type_json(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);
@ -113,6 +141,8 @@ public:
public:
virtual int res_options(SrsSocket* skt);
virtual int res_text(SrsSocket* skt, std::string body);
virtual int res_json(SrsSocket* skt, std::string json);
// object creator
public:
/**
* create http api resource handler.
@ -148,23 +178,34 @@ private:
* @remark, user can use is_complete() to determine the state.
*/
SrsHttpParseState _state;
/**
* uri parser
*/
SrsHttpUri* _uri;
/**
* best matched handler.
*/
SrsHttpHandlerMatch* _match;
public:
SrsHttpMessage();
virtual ~SrsHttpMessage();
public:
virtual void reset();
virtual int parse_uri();
public:
virtual bool is_complete();
virtual u_int8_t method();
virtual std::string url();
virtual std::string path();
virtual std::string query();
virtual std::string body();
virtual int64_t body_size();
virtual int64_t content_length();
virtual SrsHttpHandlerMatch* match();
virtual void set_url(std::string url);
virtual void set_state(SrsHttpParseState state);
virtual void set_header(http_parser* header);
virtual void set_match(SrsHttpHandlerMatch* match);
virtual void append_body(const char* body, int length);
};
@ -220,6 +261,7 @@ private:
std::string host;
int port;
std::string path;
std::string query;
public:
SrsHttpUri();
virtual ~SrsHttpUri();
@ -234,6 +276,7 @@ public:
virtual const char* get_host();
virtual int get_port();
virtual const char* get_path();
virtual const char* get_query();
private:
/**
* get the parsed url field.

@ -33,6 +33,7 @@ using namespace std;
#include <srs_app_http.hpp>
#include <srs_app_socket.hpp>
#include <srs_core_autofree.hpp>
#include <srs_app_json.hpp>
SrsApiRoot::SrsApiRoot()
{
@ -43,24 +44,28 @@ SrsApiRoot::~SrsApiRoot()
{
}
bool SrsApiRoot::can_handle(const char* path, int length, const char** pnext_path)
bool SrsApiRoot::can_handle(const char* path, int length, const char** pchild)
{
// reset the next path for child to parse.
*pnext_path = path;
// reset the child path to path,
// for child to reparse the path.
*pchild = path;
return true;
// only compare the first char.
return srs_path_equals("/", path, 1);
}
int SrsApiRoot::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/)
int SrsApiRoot::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
{
if (req->method() == HTTP_OPTIONS) {
return res_options(skt);
} else {
std::string body = "hello, root";
return res_text(skt, body);
}
return ERROR_SUCCESS;
std::stringstream ss;
ss << JOBJECT_START
<< JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT
<< JFIELD_ORG("urls", JOBJECT_START)
<< JFIELD_STR("v1", "the api version 1.0")
<< JOBJECT_END
<< JOBJECT_END;
return res_json(skt, ss.str());
}
SrsApiApi::SrsApiApi()
@ -71,21 +76,15 @@ SrsApiApi::~SrsApiApi()
{
}
bool SrsApiApi::can_handle(const char* path, int length, const char** /*pnext_path*/)
bool SrsApiApi::can_handle(const char* path, int length, const char** /*pchild*/)
{
return !memcmp("/api", path, length);
return srs_path_equals("/api", path, length);
}
int SrsApiApi::process_request(SrsSocket* skt, SrsHttpMessage* req, const char* /*path*/, int /*length*/)
int SrsApiApi::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
{
if (req->method() == HTTP_OPTIONS) {
return res_options(skt);
} else {
std::string body = "hello, api";
return res_text(skt, body);
}
return ERROR_SUCCESS;
std::string body = "hello, api";
return res_text(skt, body);
}
SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
@ -147,25 +146,31 @@ int SrsHttpApi::do_cycle()
int SrsHttpApi::process_request(SrsSocket* skt, SrsHttpMessage* req)
{
int ret = ERROR_SUCCESS;
// parse uri to schema/server:port/path?query
if ((ret = req->parse_uri()) != ERROR_SUCCESS) {
return ret;
}
// TODO: maybe need to parse the url.
std::string uri = req->url();
std::string url = req->path();
int length = 0;
const char* start = NULL;
SrsHttpHandler* p = NULL;
if ((ret = handler->best_match(uri.data(), uri.length(), &p, &start, &length)) != ERROR_SUCCESS) {
SrsHttpHandlerMatch* p = NULL;
if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) {
srs_warn("failed to find the best match handler for url. ret=%d", ret);
return ret;
}
// if success, p and pstart should be valid.
srs_assert(p);
srs_assert(start);
srs_assert(length <= (int)uri.length());
srs_assert(p->handler);
srs_assert(p->matched_url.length() <= url.length());
srs_info("best match handler, matched_url=%s", p->matched_url.c_str());
req->set_match(p);
// use handler to process request.
if ((ret = p->process_request(skt, req, start, length)) != ERROR_SUCCESS) {
if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) {
srs_warn("handler failed to process http request. ret=%d", ret);
return ret;
}

@ -48,8 +48,8 @@ public:
SrsApiRoot();
virtual ~SrsApiRoot();
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 bool can_handle(const char* path, int length, const char** pchild);
virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
};
class SrsApiApi : public SrsHttpHandler
@ -58,8 +58,8 @@ 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 bool can_handle(const char* path, int length, const char** pchild);
virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
};
class SrsHttpApi : public SrsConnection

@ -35,6 +35,7 @@ using namespace std;
#include <srs_kernel_log.hpp>
#include <srs_app_socket.hpp>
#include <srs_app_http.hpp>
#include <srs_app_json.hpp>
#define SRS_HTTP_RESPONSE_OK "0"
@ -202,32 +203,14 @@ int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, Srs
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_connect" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// pageUrl
<< '"' << "pageUrl" << '"' << ':'
<< '"' << req->pageUrl << '"'
//<< ','
<< "}";
ss << JOBJECT_START
<< JFIELD_STR("action", "on_connect") << JFIELD_CONT
<< JFIELD_ORG("client_id", client_id) << JFIELD_CONT
<< JFIELD_STR("ip", ip) << JFIELD_CONT
<< JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
<< JFIELD_STR("app", req->app) << JFIELD_CONT
<< JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
<< JOBJECT_END;
std::string data = ss.str();
std::string res;
@ -273,28 +256,14 @@ void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsR
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_close" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
//<< ','
<< "}";
ss << JOBJECT_START
<< JFIELD_STR("action", "on_close") << JFIELD_CONT
<< JFIELD_ORG("client_id", client_id) << JFIELD_CONT
<< JFIELD_STR("ip", ip) << JFIELD_CONT
<< JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
<< JFIELD_STR("app", req->app) << JFIELD_CONT
<< JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
<< JOBJECT_END;
std::string data = ss.str();
std::string res;
@ -340,32 +309,15 @@ int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, Srs
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_publish" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
ss << JOBJECT_START
<< JFIELD_STR("action", "on_publish") << JFIELD_CONT
<< JFIELD_ORG("client_id", client_id) << JFIELD_CONT
<< JFIELD_STR("ip", ip) << JFIELD_CONT
<< JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
<< JFIELD_STR("app", req->app) << JFIELD_CONT
<< JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
<< JFIELD_STR("stream", req->stream) << JFIELD_CONT
<< JOBJECT_END;
std::string data = ss.str();
std::string res;
@ -411,32 +363,15 @@ void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip,
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_unpublish" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
ss << JOBJECT_START
<< JFIELD_STR("action", "on_unpublish") << JFIELD_CONT
<< JFIELD_ORG("client_id", client_id) << JFIELD_CONT
<< JFIELD_STR("ip", ip) << JFIELD_CONT
<< JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
<< JFIELD_STR("app", req->app) << JFIELD_CONT
<< JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
<< JFIELD_STR("stream", req->stream) << JFIELD_CONT
<< JOBJECT_END;
std::string data = ss.str();
std::string res;
@ -482,32 +417,15 @@ int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsReq
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_play" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
ss << JOBJECT_START
<< JFIELD_STR("action", "on_play") << JFIELD_CONT
<< JFIELD_ORG("client_id", client_id) << JFIELD_CONT
<< JFIELD_STR("ip", ip) << JFIELD_CONT
<< JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
<< JFIELD_STR("app", req->app) << JFIELD_CONT
<< JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
<< JFIELD_STR("stream", req->stream) << JFIELD_CONT
<< JOBJECT_END;
std::string data = ss.str();
std::string res;
@ -553,32 +471,15 @@ void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRe
}
*/
std::stringstream ss;
ss << "{"
// action
<< '"' << "action" << '"' << ':'
<< '"' << "on_stop" << '"'
<< ','
// client_id
<< '"' << "client_id" << '"' << ':'
<< std::dec << client_id
<< ','
// ip
<< '"' << "ip" << '"' << ':'
<< '"' << ip << '"'
<< ','
// vhost
<< '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"'
<< ','
// app
<< '"' << "app" << '"' << ':'
<< '"' << req->app << '"'
<< ','
// stream
<< '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"'
//<< ','
<< "}";
ss << JOBJECT_START
<< JFIELD_STR("action", "on_stop") << JFIELD_CONT
<< JFIELD_ORG("client_id", client_id) << JFIELD_CONT
<< JFIELD_STR("ip", ip) << JFIELD_CONT
<< JFIELD_STR("vhost", req->vhost) << JFIELD_CONT
<< JFIELD_STR("app", req->app) << JFIELD_CONT
<< JFIELD_STR("pageUrl", req->pageUrl) << JFIELD_CONT
<< JFIELD_STR("stream", req->stream) << JFIELD_CONT
<< JOBJECT_END;
std::string data = ss.str();
std::string res;

@ -0,0 +1,24 @@
/*
The MIT License (MIT)
Copyright (c) 2013-2014 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_app_json.hpp>

@ -0,0 +1,40 @@
/*
The MIT License (MIT)
Copyright (c) 2013-2014 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_APP_JSON_HPP
#define SRS_APP_JSON_HPP
/*
#include <srs_app_json.hpp>
*/
#include <srs_core.hpp>
// json encode macros
#define JOBJECT_START "{"
#define JFIELD_STR(k, v) "\"" << k << "\":\"" << v << "\""
#define JFIELD_ORG(k, v) "\"" << k << "\":" << std::dec << v
#define JFIELD_ERROR(ret) "\"" << "code" << "\":" << ret
#define JFIELD_CONT ","
#define JOBJECT_END "}"
#endif

@ -61,6 +61,8 @@ file
..\app\srs_app_http_conn.cpp,
..\app\srs_app_http_hooks.hpp,
..\app\srs_app_http_hooks.cpp,
..\app\srs_app_json.hpp,
..\app\srs_app_json.cpp,
..\app\srs_app_log.hpp,
..\app\srs_app_log.cpp,
..\app\srs_app_refer.hpp,

Loading…
Cancel
Save