Skip to content

Commit

Permalink
增加HttpRequest参数/cookie解析
Browse files Browse the repository at this point in the history
Signed-off-by: sylar-yin <564628276@qq.com>
  • Loading branch information
sylar-yin committed Jul 13, 2019
1 parent 968f933 commit bfc681a
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 13 deletions.
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ add_library(test_module SHARED tests/test_module.cc)
sylar_add_executable(bin_sylar "sylar/main.cc" sylar "${LIBS}")
set_target_properties(bin_sylar PROPERTIES OUTPUT_NAME "sylar")

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/orm_out)
set(OLIBS ${LIBS})
set(OLIBS ${OLIBS} orm_data)
sylar_add_executable(test_orm "tests/test_orm.cc" orm_data "${OLIBS}")
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/orm_out)
#set(OLIBS ${LIBS})
#set(OLIBS ${OLIBS} orm_data)
#sylar_add_executable(test_orm "tests/test_orm.cc" orm_data "${OLIBS}")

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
2 changes: 2 additions & 0 deletions sylar/application.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "application.h"

#include <unistd.h>
#include <signal.h>

#include "sylar/tcp_server.h"
#include "sylar/daemon.h"
Expand Down Expand Up @@ -111,6 +112,7 @@ bool Application::run() {
}

int Application::main(int argc, char** argv) {
signal(SIGPIPE, SIG_IGN);
SYLAR_LOG_INFO(g_logger) << "main";
std::string conf_path = sylar::EnvMgr::GetInstance()->getConfigPath();
sylar::Config::LoadFromConfDir(conf_path, true);
Expand Down
83 changes: 81 additions & 2 deletions sylar/http/http.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "http.h"
#include "sylar/util.h"

namespace sylar {
namespace http {
Expand Down Expand Up @@ -59,6 +60,7 @@ HttpRequest::HttpRequest(uint8_t version, bool close)
,m_version(version)
,m_close(close)
,m_websocket(false)
,m_parserParamFlag(0)
,m_path("/") {
}

Expand All @@ -75,13 +77,16 @@ std::shared_ptr<HttpResponse> HttpRequest::createResponse() {
}

std::string HttpRequest::getParam(const std::string& key
,const std::string& def) const {
,const std::string& def) {
initQueryParam();
initBodyParam();
auto it = m_params.find(key);
return it == m_params.end() ? def : it->second;
}

std::string HttpRequest::getCookie(const std::string& key
,const std::string& def) const {
,const std::string& def) {
initCookies();
auto it = m_cookies.find(key);
return it == m_cookies.end() ? def : it->second;
}
Expand Down Expand Up @@ -122,6 +127,8 @@ bool HttpRequest::hasHeader(const std::string& key, std::string* val) {
}

bool HttpRequest::hasParam(const std::string& key, std::string* val) {
initQueryParam();
initBodyParam();
auto it = m_params.find(key);
if(it == m_params.end()) {
return false;
Expand All @@ -133,6 +140,7 @@ bool HttpRequest::hasParam(const std::string& key, std::string* val) {
}

bool HttpRequest::hasCookie(const std::string& key, std::string* val) {
initCookies();
auto it = m_cookies.find(key);
if(it == m_cookies.end()) {
return false;
Expand Down Expand Up @@ -184,6 +192,77 @@ std::ostream& HttpRequest::dump(std::ostream& os) const {
return os;
}

void HttpRequest::init() {
std::string conn = getHeader("connection");
if(!conn.empty()) {
if(strcasecmp(conn.c_str(), "keep-alive") == 0) {
m_close = false;
} else {
m_close = true;
}
}
}

void HttpRequest::initParam() {
initQueryParam();
initBodyParam();
initCookies();
}

void HttpRequest::initQueryParam() {
if(m_parserParamFlag & 0x1) {
return;
}

#define PARSE_PARAM(str, m, flag) \
size_t pos = 0; \
do { \
size_t last = pos; \
pos = str.find('=', pos); \
if(pos == std::string::npos) { \
break; \
} \
size_t key = pos; \
pos = str.find(flag, pos); \
m.insert(std::make_pair(str.substr(last, key - last), \
sylar::StringUtil::UrlDecode(str.substr(key + 1, pos - key - 1)))); \
if(pos == std::string::npos) { \
break; \
} \
++pos; \
} while(true);

PARSE_PARAM(m_query, m_params, '&');
m_parserParamFlag |= 0x1;
}

void HttpRequest::initBodyParam() {
if(m_parserParamFlag & 0x2) {
return;
}
std::string content_type = getHeader("content-type");
if(strcasestr(content_type.c_str(), "application/x-www-form-urlencoded") != nullptr) {
m_parserParamFlag |= 0x2;
return;
}
PARSE_PARAM(m_body, m_params, '&');
m_parserParamFlag |= 0x2;
}

void HttpRequest::initCookies() {
if(m_parserParamFlag & 0x4) {
return;
}
std::string cookie = getHeader("cookie");
if(cookie.empty()) {
m_parserParamFlag |= 0x4;
return;
}
PARSE_PARAM(cookie, m_cookies, ';');
m_parserParamFlag |= 0x4;
}


HttpResponse::HttpResponse(uint8_t version, bool close)
:m_status(HttpStatus::OK)
,m_version(version)
Expand Down
12 changes: 10 additions & 2 deletions sylar/http/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,15 +376,15 @@ class HttpRequest {
* @param[in] def 默认值
* @return 如果存在则返回对应值,否则返回默认值
*/
std::string getParam(const std::string& key, const std::string& def = "") const;
std::string getParam(const std::string& key, const std::string& def = "");

/**
* @brief 获取HTTP请求的Cookie参数
* @param[in] key 关键字
* @param[in] def 默认值
* @return 如果存在则返回对应值,否则返回默认值
*/
std::string getCookie(const std::string& key, const std::string& def = "") const;
std::string getCookie(const std::string& key, const std::string& def = "");


/**
Expand Down Expand Up @@ -537,6 +537,12 @@ class HttpRequest {
* @return 字符串
*/
std::string toString() const;

void init();
void initParam();
void initQueryParam();
void initBodyParam();
void initCookies();
private:
/// HTTP方法
HttpMethod m_method;
Expand All @@ -546,6 +552,8 @@ class HttpRequest {
bool m_close;
/// 是否为websocket
bool m_websocket;

uint8_t m_parserParamFlag;
/// 请求路径
std::string m_path;
/// 请求参数
Expand Down
6 changes: 2 additions & 4 deletions sylar/http/http_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ HttpRequest::ptr HttpSession::recvRequest() {
}
parser->getData()->setBody(body);
}
std::string keep_alive = parser->getData()->getHeader("Connection");
if(!strcasecmp(keep_alive.c_str(), "keep-alive")) {
parser->getData()->setClose(false);
}

parser->getData()->init();
return parser->getData();
}

Expand Down
2 changes: 1 addition & 1 deletion sylar/log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ class LexicalCast<LogDefine, std::string> {
if(i.level != LogLevel::UNKNOW) {
n["level"] = LogLevel::ToString(i.level);
}
if(i.formatter.empty()) {
if(!i.formatter.empty()) {
n["formatter"] = i.formatter;
}

Expand Down
5 changes: 5 additions & 0 deletions sylar/main.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#include "sylar/application.h"
#include <stdlib.h>
#include <time.h>

int main(int argc, char** argv) {
setenv("TZ", ":/etc/localtime", 1);
tzset();
srand(time(0));
sylar::Application app;
if(app.init(argc, argv)) {
return app.run();
Expand Down
109 changes: 109 additions & 0 deletions sylar/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -358,4 +358,113 @@ std::string StringUtil::Formatv(const char* fmt, va_list ap) {
return ret;
}

static const char uri_chars[256] = {
/* 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
/* 64 */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
/* 128 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 192 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

static const char xdigit_chars[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};

#define CHAR_IS_UNRESERVED(c) \
(uri_chars[(unsigned char)(c)])

//-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~
std::string StringUtil::UrlEncode(const std::string& str, bool space_as_plus) {
static const char *hexdigits = "0123456789ABCDEF";
std::string* ss = nullptr;
const char* end = str.c_str() + str.length();
for(const char* c = str.c_str() ; c < end; ++c) {
if(!CHAR_IS_UNRESERVED(*c)) {
if(!ss) {
ss = new std::string;
ss->reserve(str.size() * 1.2);
ss->append(str.c_str(), c - str.c_str());
}
if(*c == ' ' && space_as_plus) {
ss->append(1, '+');
} else {
ss->append(1, '%');
ss->append(1, hexdigits[(uint8_t)*c >> 4]);
ss->append(1, hexdigits[*c & 0xf]);
}
} else if(ss) {
ss->append(1, *c);
}
}
if(!ss) {
return str;
} else {
std::string rt = *ss;
delete ss;
return rt;
}
}

std::string StringUtil::UrlDecode(const std::string& str, bool space_as_plus) {
std::string* ss = nullptr;
const char* end = str.c_str() + str.length();
for(const char* c = str.c_str(); c < end; ++c) {
if(*c == '+' && space_as_plus) {
if(!ss) {
ss = new std::string;
ss->append(str.c_str(), c - str.c_str());
}
ss->append(1, ' ');
} else if(*c == '%' && (c + 2) < end
&& isxdigit(*(c + 1)) && isxdigit(*(c + 2))){
if(!ss) {
ss = new std::string;
ss->append(str.c_str(), c - str.c_str());
}
ss->append(1, (char)(xdigit_chars[(int)*(c + 1)] << 4 | xdigit_chars[(int)*(c + 2)]));
c += 2;
} else if(ss) {
ss->append(1, *c);
}
}
if(!ss) {
return str;
} else {
std::string rt = *ss;
delete ss;
return rt;
}
}


}
3 changes: 3 additions & 0 deletions sylar/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ class StringUtil {
public:
static std::string Format(const char* fmt, ...);
static std::string Formatv(const char* fmt, va_list ap);

static std::string UrlEncode(const std::string& str, bool space_as_plus = true);
static std::string UrlDecode(const std::string& str, bool space_as_plus = true);
};

}
Expand Down

0 comments on commit bfc681a

Please sign in to comment.