Title:cpp-netlib笔记三-Cookie支持测试
Author:Kagula
Date:2017-06-02
Environment:
[1]Boost 1.64
本机安装目录 D:\SDK\boost_1_64_0
[2]Windows10、VS2017 Update2
[3]OpenCL 1.0.2k本机安装目录
D:\SDK\OpenSSL_1_0_2k_vc2007
[4]CMake 3.8.1
[5]cpp-netlib-0.12.0-final
本机安装目录 D:\SDK\cpp-netlib-0.12.0-final
[6]Python 3.6.1
[7]ActivePerl 5.16
[8]IE11、Chrome 58.0.3029.110 、Postman
Introduction:
测试cpp-netlib对Cookie的支持,直接贴代码。
源码清单
#include <thread>
#include <boost/network/protocol/http/server.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <sstream>
#include <iomanip>
using namespace std;
namespace http = boost::network::http;
namespace utils = boost::network::utils;
struct counter_server;
typedef http::server<counter_server> server;
//用来存放每个seesion对应的计数值。
//由于这里的代码目的是做技术可行性分析,所以没做线程同步控制.
map<string, int> g_session;
//在Cookie中标记我们session的key
string g_sessionKey("CSessionID");
//用于为每个session分配不同的编号
unsigned g_sessionIndex = 0;
/*
《http状态码一览表以及HTTP响应的返回头信息(支持跳转》
http://blog.sina.com.cn/s/blog_415bd7070100en9i.html
*/
//
struct counter_server {
explicit counter_server() {}
void operator()(server::request const &request,
server::connection_ptr connection) {
//找Cookie.
string cookie;
for (const auto& header : request.headers) {
std::string lowerCaseName;
lowerCaseName.resize(header.name.size());
std::transform(header.name.begin(), header.name.end(),
lowerCaseName.begin(), ::tolower);
if (lowerCaseName == "cookie")
{
cookie = header.value;
break;
}//if
}//for
//如果有Cookie,把session id分离出来。
std::string sessionID;
if (cookie.empty() == false)
{
std::vector<std::string> vecRec;
boost::split(vecRec, cookie, boost::is_any_of(";"));
for (unsigned i = 0; i < vecRec.size(); i++)
{
std::vector<std::string> vecSub;
boost::split(vecSub, vecRec[i], boost::is_any_of("="));
if (vecSub.size() == 2)
{
boost::trim_if(vecSub[0], boost::is_any_of("\" \n\r\t'"));
boost::trim_if(vecSub[1], boost::is_any_of("\" \n\r\t'"));
if (vecSub[0] == g_sessionKey)
{
sessionID = vecSub[1];
break;
}
}//end if
}//end for
}//end if
//如果没有session id,分配一个session id
if (sessionID.empty()||g_session.find(sessionID)==g_session.end())
{
g_sessionIndex++;
sessionID = std::to_string(g_sessionIndex);
g_session[sessionID] = 0;
}
g_session[sessionID]++;
string content = [](const std::string &sessionID)->string{
stringstream ss;
ss << "sessionID=" << sessionID << "," << "counter=" << g_session[sessionID];
return ss.str();
}(sessionID);
static server::response_header headers[] = {
{ "Server", "cpp-netlib-0.12.0-final" },
{ "Connection", "close" },
{ "Content-Type", "text/plain" },//Content-Type: text/html; charset=UTF-8
{ "Set-Cookie", "" },
{ "Content-Length", "0" },
{ "Access-Control-Allow-Origin", "*" }, //没有这个设定chrome每次会让服务端这个方法进入两次。
{ "Cache-Control", "no-cache" },
{ "Date", "Fri, 02 Jun 2017 01:24:55 GMT" }
};
stringstream ss;
ss << g_sessionKey << "=" << sessionID << "; path=/";
headers[3].value = ss.str();
//Set-Cookie: lasthandler=1247645572; expires=Wed, 15-Jul-2009 09:12:52 GMT; path=/; domain=yoka.com
headers[4].value = std::to_string(content.size());
headers[7].value = []() ->string{
using namespace boost::gregorian;
date today(day_clock::universal_day());//获取GMT日期
const boost::posix_time::ptime now(today,
boost::posix_time::second_clock::universal_time().time_of_day());
const boost::posix_time::time_duration td = now.time_of_day();
stringstream ss;
ss << today.day_of_week() << ", " << today.day() << " " << today.month() << " " << today.year() << " ";
ss << setw(2) << setfill('0') << td.hours() << ":";
ss << setw(2) << setfill('0') << td.minutes() << ":";
ss << setw(2) << setfill('0') << td.seconds() << " GMT";
return ss.str();
}();
connection->set_status(server::connection::ok);//200
connection->set_headers(
boost::make_iterator_range(headers, headers + 8));
connection->write(content);
}
};
#ifdef _WIN32
#pragma comment(lib, "cppnetlib-server-parsers.lib")
#endif
int main(int argc, char** argv)
{
cout << "技术可行性测试!" << endl;
cout << "通过一个计数器Demo,来测试Cookie的支持!" << endl;
try {
counter_server handler;
server::options options(handler);
server instance(options.thread_pool(std::make_shared<utils::thread_pool>(4))
.address("0.0.0.0")
.port("8080"));
instance.run();
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
总结
通过这个示例,证实cpp-netlib支持session是没有问题的。