feat: add cpp example for http
This commit is contained in:
parent
670093e42a
commit
29505b6ec2
|
@ -31,9 +31,20 @@ int connection_num = 0;
|
||||||
//2. index.html: only query (maybe load/unload if using multiple databases)
|
//2. index.html: only query (maybe load/unload if using multiple databases)
|
||||||
//3. ghttp: can add or not add a db as parameter
|
//3. ghttp: can add or not add a db as parameter
|
||||||
//BETTER: How about change HttpConnector into a console?
|
//BETTER: How about change HttpConnector into a console?
|
||||||
|
//
|
||||||
//TODO: we need a route
|
//TODO: we need a route
|
||||||
//JSON parser: http://www.tuicool.com/articles/yUJb6f
|
//JSON parser: http://www.tuicool.com/articles/yUJb6f
|
||||||
//(or use boost spirit to generate parser when compiling)
|
//(or use boost spirit to generate parser when compiling)
|
||||||
|
//
|
||||||
|
//NOTICE: no need to close connection here due to the usage of shared_ptr
|
||||||
|
//http://www.tuicool.com/articles/3Ub2y2
|
||||||
|
//
|
||||||
|
//TODO: the URL format is terrible, i.e. 127.0.0.1:8080/build/lubm/data/LUBM_10.n3
|
||||||
|
//we should define some keys like operation, database, dataset, query, path ...
|
||||||
|
//127.0.0.1:8080?operation=build&database=lubm&dataset=data/LUBM_10.n3
|
||||||
|
//
|
||||||
|
//TODO: control the authority, check it if requesting for build/load/unload
|
||||||
|
//for sparql endpoint, just load database when starting, and comment out all functions except for query()
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
Util util;
|
Util util;
|
||||||
|
@ -50,6 +61,7 @@ int main() {
|
||||||
//server.resource["^/build/([a-zA-Z]+[0-9]*)/([a-zA-Z]+/*[a-zA-Z]+[0-9]*.n[a-zA-Z]*[0-9]*)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
//server.resource["^/build/([a-zA-Z]+[0-9]*)/([a-zA-Z]+/*[a-zA-Z]+[0-9]*.n[a-zA-Z]*[0-9]*)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
// server.resource["^/build/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
// server.resource["^/build/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
server.resource["^/build/([a-zA-Z0-9]*)/(.*)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
server.resource["^/build/([a-zA-Z0-9]*)/(.*)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
|
cout<<"HTTP: this is build"<<endl;
|
||||||
string db_name=request->path_match[1];
|
string db_name=request->path_match[1];
|
||||||
string db_path=request->path_match[2];
|
string db_path=request->path_match[2];
|
||||||
if(db_name=="" || db_path=="")
|
if(db_name=="" || db_path=="")
|
||||||
|
@ -104,6 +116,7 @@ int main() {
|
||||||
//GET-example for the path /load/[db_name], responds with the matched string in path
|
//GET-example for the path /load/[db_name], responds with the matched string in path
|
||||||
//For instance a request GET /load/db123 will receive: db123
|
//For instance a request GET /load/db123 will receive: db123
|
||||||
server.resource["^/load/(.*)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
server.resource["^/load/(.*)$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
|
cout<<"HTTP: this is load"<<endl;
|
||||||
string db_name=request->path_match[1];
|
string db_name=request->path_match[1];
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,6 +167,7 @@ int main() {
|
||||||
//GET-example for the path /query/[query_file_path], responds with the matched string in path
|
//GET-example for the path /query/[query_file_path], responds with the matched string in path
|
||||||
//For instance a request GET /query/db123 will receive: db123
|
//For instance a request GET /query/db123 will receive: db123
|
||||||
server.resource["^/query/(.*)$"]["GET"] = [&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
server.resource["^/query/(.*)$"]["GET"] = [&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
|
cout<<"HTTP: this is query"<<endl;
|
||||||
string db_query=request->path_match[1];
|
string db_query=request->path_match[1];
|
||||||
string str = db_query;
|
string str = db_query;
|
||||||
|
|
||||||
|
@ -213,6 +227,7 @@ int main() {
|
||||||
//GET-example for the path /unload/[db_name], responds with the matched string in path
|
//GET-example for the path /unload/[db_name], responds with the matched string in path
|
||||||
//For instance a request GET /unload/db123 will receive: db123
|
//For instance a request GET /unload/db123 will receive: db123
|
||||||
server.resource["^/unload$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
server.resource["^/unload$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
|
cout<<"HTTP: this is unload"<<endl;
|
||||||
if(current_database == NULL)
|
if(current_database == NULL)
|
||||||
{
|
{
|
||||||
string error = "No database used now.";
|
string error = "No database used now.";
|
||||||
|
@ -228,6 +243,7 @@ int main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
server.resource["^/monitor$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
server.resource["^/monitor$"]["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
|
cout<<"HTTP: this is monitor"<<endl;
|
||||||
if(current_database == NULL)
|
if(current_database == NULL)
|
||||||
{
|
{
|
||||||
string error = "No database used now.";
|
string error = "No database used now.";
|
||||||
|
@ -284,6 +300,7 @@ int main() {
|
||||||
//Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
|
//Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
|
||||||
server.default_resource["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
server.default_resource["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||||
//BETTER: use lock to ensure thread safe
|
//BETTER: use lock to ensure thread safe
|
||||||
|
cout<<"HTTP: this is default"<<endl;
|
||||||
connection_num++;
|
connection_num++;
|
||||||
//NOTICE: it seems a visit will output twice times
|
//NOTICE: it seems a visit will output twice times
|
||||||
//And different pages in a browser is viewed as two connections here
|
//And different pages in a browser is viewed as two connections here
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
example: example.cpp client.cpp client.h
|
||||||
|
g++ -o example example.cpp client.cpp -lcurl
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm *.o example
|
|
@ -0,0 +1,194 @@
|
||||||
|
#include "client.h"
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
CHttpClient::CHttpClient(void) :
|
||||||
|
m_bDebug(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CHttpClient::~CHttpClient(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
|
||||||
|
{
|
||||||
|
if(itype == CURLINFO_TEXT)
|
||||||
|
{
|
||||||
|
//printf("[TEXT]%s\n", pData);
|
||||||
|
}
|
||||||
|
else if(itype == CURLINFO_HEADER_IN)
|
||||||
|
{
|
||||||
|
printf("[HEADER_IN]%s\n", pData);
|
||||||
|
}
|
||||||
|
else if(itype == CURLINFO_HEADER_OUT)
|
||||||
|
{
|
||||||
|
printf("[HEADER_OUT]%s\n", pData);
|
||||||
|
}
|
||||||
|
else if(itype == CURLINFO_DATA_IN)
|
||||||
|
{
|
||||||
|
printf("[DATA_IN]%s\n", pData);
|
||||||
|
}
|
||||||
|
else if(itype == CURLINFO_DATA_OUT)
|
||||||
|
{
|
||||||
|
printf("[DATA_OUT]%s\n", pData);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
|
||||||
|
{
|
||||||
|
std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
|
||||||
|
if( NULL == str || NULL == buffer )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* pData = (char*)buffer;
|
||||||
|
str->append(pData, size * nmemb);
|
||||||
|
return nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CHttpClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)
|
||||||
|
{
|
||||||
|
strResponse.clear();
|
||||||
|
CURLcode res;
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
if(NULL == curl)
|
||||||
|
{
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
}
|
||||||
|
if(m_bDebug)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CHttpClient::Get(const std::string & strUrl, std::string & strResponse)
|
||||||
|
{
|
||||||
|
strResponse.clear();
|
||||||
|
CURLcode res;
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
if(NULL == curl)
|
||||||
|
{
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
}
|
||||||
|
if(m_bDebug)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
|
||||||
|
/**
|
||||||
|
* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
|
||||||
|
* 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
|
||||||
|
*/
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CHttpClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)
|
||||||
|
{
|
||||||
|
strResponse.clear();
|
||||||
|
CURLcode res;
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
if(NULL == curl)
|
||||||
|
{
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
}
|
||||||
|
if(m_bDebug)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
if(NULL == pCaPath)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//缺省情况就是PEM,所以无需设置,另外支持DER
|
||||||
|
//curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CHttpClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)
|
||||||
|
{
|
||||||
|
strResponse.clear();
|
||||||
|
CURLcode res;
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
if(NULL == curl)
|
||||||
|
{
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
}
|
||||||
|
if(m_bDebug)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
if(NULL == pCaPath)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void CHttpClient::SetDebug(bool bDebug)
|
||||||
|
{
|
||||||
|
m_bDebug = bDebug;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
#ifndef __HTTP_CURL_H__
|
||||||
|
#define __HTTP_CURL_H__
|
||||||
|
|
||||||
|
//REFERENCE: https://curl.haxx.se/
|
||||||
|
//
|
||||||
|
//TODO: deal with cookie
|
||||||
|
//URL encode: http://www.ruanyifeng.com/blog/2010/02/url_encoding.html
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class CHttpClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CHttpClient(void);
|
||||||
|
~CHttpClient(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief HTTP POST请求
|
||||||
|
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
|
||||||
|
* @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
|
||||||
|
* @param strResponse 输出参数,返回的内容
|
||||||
|
* @return 返回是否Post成功
|
||||||
|
*/
|
||||||
|
int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HTTP GET请求
|
||||||
|
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
|
||||||
|
* @param strResponse 输出参数,返回的内容
|
||||||
|
* @return 返回是否Post成功
|
||||||
|
*/
|
||||||
|
int Get(const std::string & strUrl, std::string & strResponse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HTTPS POST请求,无证书版本
|
||||||
|
* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
|
||||||
|
* @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
|
||||||
|
* @param strResponse 输出参数,返回的内容
|
||||||
|
* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
|
||||||
|
* @return 返回是否Post成功
|
||||||
|
*/
|
||||||
|
int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HTTPS GET请求,无证书版本
|
||||||
|
* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
|
||||||
|
* @param strResponse 输出参数,返回的内容
|
||||||
|
* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
|
||||||
|
* @return 返回是否Post成功
|
||||||
|
*/
|
||||||
|
int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void SetDebug(bool bDebug);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_bDebug;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
||||||
|
//NOTICE: you need to use libcurl-devel for C++ to use HTTP client, please read client.cpp and client.h seriously
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CHttpClient hc;
|
||||||
|
string res;
|
||||||
|
int ret;
|
||||||
|
//NOTICE: here no need to add admin.html
|
||||||
|
ret = hc.Get("127.0.0.1:8080/build/lubm/data/LUBM_10.n3", res);
|
||||||
|
cout<<res<<endl;
|
||||||
|
ret = hc.Get("127.0.0.1:8080/load/lubm", res);
|
||||||
|
cout<<res<<endl;
|
||||||
|
ret = hc.Get("127.0.0.1:8080/query/data/ex0.sql", res);
|
||||||
|
cout<<res<<endl;
|
||||||
|
ret = hc.Get("127.0.0.1:8080/monitor", res);
|
||||||
|
cout<<res<<endl;
|
||||||
|
ret = hc.Get("127.0.0.1:8080/unload", res);
|
||||||
|
cout<<res<<endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue