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)
|
||||
//3. ghttp: can add or not add a db as parameter
|
||||
//BETTER: How about change HttpConnector into a console?
|
||||
//
|
||||
//TODO: we need a route
|
||||
//JSON parser: http://www.tuicool.com/articles/yUJb6f
|
||||
//(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() {
|
||||
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-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) {
|
||||
cout<<"HTTP: this is build"<<endl;
|
||||
string db_name=request->path_match[1];
|
||||
string db_path=request->path_match[2];
|
||||
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
|
||||
//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) {
|
||||
cout<<"HTTP: this is load"<<endl;
|
||||
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
|
||||
//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) {
|
||||
cout<<"HTTP: this is query"<<endl;
|
||||
string db_query=request->path_match[1];
|
||||
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
|
||||
//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) {
|
||||
cout<<"HTTP: this is unload"<<endl;
|
||||
if(current_database == NULL)
|
||||
{
|
||||
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) {
|
||||
cout<<"HTTP: this is monitor"<<endl;
|
||||
if(current_database == NULL)
|
||||
{
|
||||
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
|
||||
server.default_resource["GET"]=[&server](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
|
||||
//BETTER: use lock to ensure thread safe
|
||||
cout<<"HTTP: this is default"<<endl;
|
||||
connection_num++;
|
||||
//NOTICE: it seems a visit will output twice times
|
||||
//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