利用gsoap库封装易用的rest框架
c++缺少web开发的框架,web框架分为异步和同步,异步的业务逻辑控制需要较强功底,同步代码实现起来容易,利于阅读理解
1.gsoap是c++写的webservice库,webservice应用层也是用http进行传输的,gsoap提供了httpget和httppost的插件,本文对这两个插件进行改造,可以支持restful风格的接口。下面是的代码需要在c++11支持的编译器下运行,rest包装的内容用json传递
2.利于gsoap的soapcpp2.exe工具生成env文件
命令
mkdir env
soapcpp2.exe -penv -denv env.h
3.拷贝源码目录下的stdsoap2.h和stdsoap2.cpp,和http插件包含进你的工程
4.server文件
- #ifndef SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
- #define SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
- #include <string>
- #include <map>
- #include <list>
- #include <queue>
- #include <mutex>
- #include <condition_variable>
- #include <thread>
- using namespace std;
- #include "stdsoap2.h"
- #include "RestServicePlugin.h"
- using namespace Http;
- class CSoapWebServer
- {
- public:
- CSoapWebServer();
- ~CSoapWebServer();
- static const int AcceptTimeout = ;//>单位s
- static const int RecvTimeout = ;//>单位s
- static const int SendTimeout = ;//>单位s
- static const int MaxThreadCount = ;
- static const unsigned int WaitTimeout = ; //>单位s
- void SetURI(const char* URI,RequestProcessFunc fun, void * user);
- void SetURI(const char* URI, RequestProcessFunction & fun);
- void ResetURI(const char* URI);
- void ClearURI();
- bool StartService(const char* ip,unsigned int port);
- void StopService();
- protected:
- struct THREAD_INFO
- {
- struct soap* soap_listen;
- struct soap* soap_client;
- CSoapWebServer* pThis;
- };
- bool StartThread();
- void CloseThread();
- void ServiceListenThread();
- void ServiceServeThread(THREAD_INFO*pParam);
- void Listen();
- void ExecuteServe(THREAD_INFO* info);
- int SoapServ(struct soap* soap);
- int BeginServe(struct soap* soap);
- int EndServe(struct soap* soap);
- struct soap* PopSoap(void);
- void PushSoap(struct soap* soap);
- void FreeSoapAll(void);
- private:
- CRestServicePlugin m_service;
- struct soap* m_pSoap;
- volatile bool m_bExit;
- std::thread *m_ListenThread; //>接收线程句柄
- std::thread *m_ServeThread[MaxThreadCount]; //>服务执行线程
- struct CLIENT_INFO
- {
- SOAP_SOCKET socket;
- unsigned long ip;
- unsigned int port;
- };
- std::queue<CLIENT_INFO> m_acceptClientList;
- std::queue<struct soap*> m_soapList;
- std::mutex m_listMt;
- std::condition_variable m_cvClient;
- unsigned int m_iClientCount;
- };
- #endif // SoapWebServer_279437A4_6013_4E56_B152_EC3D528A0CC2_H__
- 5.server.cpp文件
- #include "SoapWebServer.h"
- //#include "soap.nsmap"
- SOAP_NMAC struct Namespace namespaces[] = {
- {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL},
- {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL},
- {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
- {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
- {NULL, NULL, NULL, NULL}
- };
- int TestAPI(Request& request)
- {
- char* body = NULL;
- size_t body_len = request.GetBody(&body);
- Response res(request);
- res.SetContentType("text/json");
- res.Send("{\"name\":\"bobo\",\"age\": 50}");
- return SOAP_OK;
- }
- CSoapWebServer::CSoapWebServer():
- m_pSoap(NULL),
- m_bExit(false),
- m_ListenThread(nullptr),
- m_iClientCount()
- {
- for (int i = ; i < MaxThreadCount; ++i)
- {
- m_ServeThread[i] = nullptr;
- }
- }
- CSoapWebServer::~CSoapWebServer()
- {
- }
- void CSoapWebServer::ClearURI()
- {
- m_service.ClearURI();
- }
- void CSoapWebServer::ResetURI( const char* URI )
- {
- if (URI)
- {
- m_service.UnRegisteURI(URI);
- }
- }
- void CSoapWebServer::SetURI( const char* URI,RequestProcessFunc fun, void * user)
- {
- if (!URI || !fun)
- {
- return;
- }
- m_service.RegisteURI(URI,fun, user);
- }
- void CSoapWebServer::SetURI(const char* URI, RequestProcessFunction & fun)
- {
- if (!URI || !fun)
- {
- return;
- }
- m_service.RegisteURI(URI,fun);
- }
- bool CSoapWebServer::StartService(const char* ip,unsigned int port)
- {
- //StopService();
- m_bExit = false;
- do
- {
- m_pSoap = soap_new();
- if (NULL == m_pSoap)
- {
- break;
- }
- soap_init1(m_pSoap, SOAP_C_UTFSTRING);
- m_pSoap->bind_flags = SO_REUSEADDR;
- m_pSoap->send_timeout = SendTimeout;
- m_pSoap->recv_timeout = RecvTimeout;
- m_pSoap->accept_timeout = AcceptTimeout;
- m_pSoap->imode = SOAP_C_UTFSTRING;
- m_pSoap->namespaces = namespaces;
- soap_set_local_namespaces(m_pSoap);
- m_service.Hook(m_pSoap);
- {
- FreeSoapFunction fun((FreeSoapFunction)std::tr1::bind(
- &CSoapWebServer::PushSoap, this, std::tr1::placeholders::_1));
- m_service.RegisterFreeSoap(fun);
- }
- SOAP_SOCKET serverSocket = soap_bind(m_pSoap,ip,port,);
- if (serverSocket == SOAP_INVALID_SOCKET)
- {
- printf("err soap_bind, %s:%u\n", ip, port);
- break;
- }
- printf("soap bind %s:%u\n", ip, port);
- if (!StartThread())
- {
- printf("err StartThread\n");
- break;
- }
- printf("start success\n");
- return true;
- } while (false);
- printf("err start failed\n");
- StopService();
- return false;
- }
- void CSoapWebServer::StopService()
- {
- m_bExit = true;
- CloseThread();
- m_iClientCount = ;
- m_service.ClearURI();
- FreeSoapAll();
- if (NULL != m_pSoap)
- {
- soap_destroy(m_pSoap);
- soap_end(m_pSoap);
- soap_done(m_pSoap);
- soap_free(m_pSoap);
- m_pSoap = NULL;
- }
- }
- bool CSoapWebServer::StartThread()
- {
- //>开启service接受执行线程
- m_ListenThread = new std::thread(
- &CSoapWebServer::ServiceListenThread,this);
- int iThreadCount = ;
- if( iThreadCount > MaxThreadCount)
- {
- iThreadCount = MaxThreadCount;
- }
- else if(iThreadCount == )
- {
- iThreadCount = ;
- }
- for (int i = ; i < iThreadCount; ++i)
- {
- soap* pSoap = soap_copy(m_pSoap);
- THREAD_INFO* info = new(std::nothrow)THREAD_INFO;
- if (info == NULL)
- {
- return false;
- }
- info->soap_listen = m_pSoap;
- info->soap_client = pSoap;
- info->pThis = this;
- m_ServeThread[i] = new std::thread(
- &CSoapWebServer::ServiceServeThread, this, info);
- }
- return true;
- }
- void CSoapWebServer::CloseThread()
- {
- m_cvClient.notify_all();
- if (m_ListenThread)
- {
- m_ListenThread->join();
- delete m_ListenThread;
- m_ListenThread = nullptr;
- }
- for (int i = ; i < MaxThreadCount; i++)
- {
- if(m_ServeThread[i])
- {
- m_ServeThread[i]->join();
- delete m_ServeThread[i];
- m_ServeThread[i] = nullptr;
- }
- }
- }
- void CSoapWebServer::ServiceListenThread()
- {
- Listen();
- return ;
- }
- void CSoapWebServer::Listen()
- {
- if (NULL == m_pSoap)
- {
- return ;
- }
- CLIENT_INFO clientInfo;
- while (!m_bExit)
- {
- clientInfo.socket = soap_accept(m_pSoap);
- if (clientInfo.socket != SOAP_INVALID_SOCKET )
- {
- std::unique_lock<std::mutex> guard(m_listMt);
- clientInfo.ip = m_pSoap->ip;
- clientInfo.port = m_pSoap->port;
- m_acceptClientList.push(clientInfo);
- ++m_iClientCount;
- m_cvClient.notify_one();
- }
- }
- }
- void CSoapWebServer::ServiceServeThread(THREAD_INFO* pParam )
- {
- if (NULL == pParam)
- {
- return ;
- }
- THREAD_INFO* info = (THREAD_INFO*)pParam;
- CSoapWebServer *pThis = info->pThis;
- if(NULL == pThis)
- {
- return ;
- }
- ExecuteServe(info);
- delete info;
- return ;
- }
- void CSoapWebServer::ExecuteServe(THREAD_INFO* info )
- {
- const int iTempSockCount = ;
- CLIENT_INFO tempClientArr[iTempSockCount] = {};
- int end_pos = ;
- struct soap* soap = NULL;
- soap = info->soap_client;
- int ret = SOAP_OK;
- while (!m_bExit)
- {
- {
- std::unique_lock<std::mutex> guard(m_listMt);
- if (m_acceptClientList.empty())
- {
- m_cvClient.wait(guard);
- }
- for (end_pos=;
- end_pos<iTempSockCount && !m_acceptClientList.empty();
- ++end_pos )
- {
- tempClientArr[end_pos] = m_acceptClientList.front();
- m_acceptClientList.pop();
- --m_iClientCount;
- }
- }
- for (int i = ; i < end_pos; ++i)
- {
- soap->socket = tempClientArr[i].socket;
- soap->ip = tempClientArr[i].ip;
- soap->port = tempClientArr[i].port;
- if(!soap_valid_socket(soap->socket))
- {
- continue;
- }
- if ((ret=BeginServe(soap)) != SOAP_OK)
- {
- //printf("serve error.code:%d msg:%s\n", soap->error,*(soap_faultstring(soap)));
- }
- if (ret == SOAP_STOP/*(int)soap->user == RESPONSE_MODE_ASYN*/)
- {//异步
- //获取一个soap
- soap = PopSoap();
- if (soap == NULL)
- {//缓存没有,拷贝一个
- soap = soap_copy(info->soap_listen);
- }
- }
- else
- {
- EndServe(soap);
- }
- soap_destroy(soap);
- soap_end(soap);
- }
- }
- //回收
- PushSoap(soap);
- }
- int CSoapWebServer::SoapServ( struct soap* soap )
- {
- #ifndef WITH_FASTCGI
- unsigned int k = soap->max_keep_alive;
- #endif
- do
- {
- #ifndef WITH_FASTCGI
- if (soap->max_keep_alive > && !--k)
- {
- soap->keep_alive = ;
- }
- #endif
- if (soap_begin_serve(soap))
- {
- if (soap->error >= SOAP_STOP)
- {
- continue;
- }
- return soap->error;
- }
- #ifdef WITH_FASTCGI
- soap_destroy(soap);
- soap_end(soap);
- } while ();
- #else
- } while (soap->keep_alive);
- #endif
- return SOAP_OK;
- }
- int CSoapWebServer::BeginServe(struct soap* soap)
- {
- void * user = soap->user;
- long ret = RESPONSE_MODE_SYN;
- soap_begin(soap);
- if (soap_begin_recv(soap)
- || soap_envelope_begin_in(soap)
- || soap_recv_header(soap)
- || soap_body_begin_in(soap))
- { if (soap->error < SOAP_STOP)
- {
- #ifdef WITH_FASTCGI
- (void)soap_send_fault(soap);
- #else
- return soap_send_fault(soap);
- #endif
- }
- }
- ret = (long)soap->user;
- soap->user = user;
- return (ret==RESPONSE_MODE_ASYN) ? SOAP_STOP: SOAP_OK;
- }
- int CSoapWebServer::EndServe(struct soap* soap)
- {
- return soap_closesock(soap);
- }
- struct soap* CSoapWebServer::PopSoap(void)
- {
- struct soap * soap = NULL;
- std::unique_lock<std::mutex> guard(m_listMt);
- if (m_soapList.empty())
- {
- return NULL;
- }
- soap = m_soapList.front();
- m_soapList.pop();
- return soap;
- }
- void CSoapWebServer::PushSoap(struct soap* soap)
- {
- if (soap == NULL)
- {
- return ;
- }
- std::unique_lock<std::mutex> guard(m_listMt);
- m_soapList.push(soap);
- }
- void CSoapWebServer::FreeSoapAll(void)
- {
- std::queue<struct soap*> lsoap;
- {
- std::unique_lock<std::mutex> guard(m_listMt);
- lsoap = m_soapList;
- while (!m_soapList.empty())
- {
- m_soapList.pop();
- }
- }
- struct soap * soap;
- while (!lsoap.empty())
- {
- soap = lsoap.front();
- soap_destroy(soap);
- soap_end(soap);
- soap_done(soap);
- soap_free(soap);
- lsoap.pop();
- }
- }
6.插件头文件
- #ifndef RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
- #define RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
- #include <string>
- #include <map>
- #include <mutex>
- #if (defined _WIN32 || defined _WIN64)
- # include <memory> //shared_ptr
- # include <functional>
- #elif defined(__linux__)
- # include <tr1/memory>
- # include <tr1/functional>
- #endif
- #include "stdsoap2.h"
- #include "httpget.h"
- #include "httppost.h"
- namespace Http
- {
- class CRestServicePlugin;
- class Request;
- typedef int (*RequestProcessFunc)(Request& request, void* user);
- typedef std::tr1::function<int(Request& request)> RequestProcessFunction;
- typedef std::tr1::function<void(struct soap*)> FreeSoapFunction;
- enum HTTP_STATUS
- {
- HTTP_STATUS_OK = ,
- HTTP_STATUS_BAD_REQUEST = , // invalid syntax
- HTTP_STATUS_DENIED = , // access denied
- HTTP_STATUS_PAYMENT_REQ = , // payment required
- HTTP_STATUS_FORBIDDEN = , // request forbidden
- HTTP_STATUS_NOT_FOUND = , // object not found
- HTTP_STATUS_BAD_METHOD = , // method is not allowed
- HTTP_STATUS_NONE_ACCEPTABLE = , // no response acceptable to client found
- HTTP_STATUS_PROXY_AUTH_REQ = , // proxy authentication required
- HTTP_STATUS_REQUEST_TIMEOUT = , // server timed out waiting for request
- HTTP_STATUS_CONFLICT = , // user should resubmit with more info
- HTTP_STATUS_GONE = , // the resource is no longer available
- HTTP_STATUS_LENGTH_REQUIRED = , // the server refused to accept request w/o a length
- HTTP_STATUS_PRECOND_FAILED = , // precondition given in request failed
- HTTP_STATUS_REQUEST_TOO_LARGE = , // request entity was too large
- HTTP_STATUS_URI_TOO_LONG = , // request URI too long
- HTTP_STATUS_UNSUPPORTED_MEDIA = , // unsupported media type
- HTTP_STATUS_RETRY_WITH = , // retry after doing the appropriate action.
- HTTP_STATUS_SERVER_ERROR = ,// internal server error
- HTTP_STATUS_NOT_SUPPORTED = , // required not supported
- HTTP_STATUS_BAD_GATEWAY = , // error response received from gateway
- HTTP_STATUS_SERVICE_UNAVAIL = , // temporarily overloaded
- HTTP_STATUS_GATEWAY_TIMEOUT = , // timed out waiting for gateway
- HTTP_STATUS_VERSION_NOT_SUP = // HTTP version not supported
- };
- enum HTTP_METHOD
- {
- HTTP_GET = ,
- HTTP_POST =
- };
- enum HTTP_RES_TYPE
- {
- HTTP_HTML = ,
- HTTP_FILE =
- };
- typedef struct rest_str_s
- {
- size_t len; //字符串长度
- char* ptr; //字符串首地址
- }rest_str_t;
- typedef struct rest_query_s
- {
- const char* key;
- const char* value;
- }rest_query_t;
- static const size_t QUERY_MAX_SIZE = ; //最多参数个数
- class Request
- {
- friend class CRestServicePlugin;
- friend class Response;
- public:
- Request()
- {
- soap = NULL;
- }
- /** @fn Query
- * @brief 获取url中的请求参数
- * @param key:
- * @return 返回查询到的值
- */
- const char* Query( const char* key);
- /** @fn GetBody
- * @brief 获取请求体
- * @param
- * @return 请求内容字节数,0为空
- */
- size_t GetBody(char** body);
- HTTP_METHOD GetMethod(void){ return method;}
- protected:
- /** @fn GetURI
- * @brief 获取请求的url
- * @param
- * @return
- */
- const char* GetURI();
- int ReponseWithEnd(int code);
- /************************************
- >@ Method: ParseRequest
- >@ FullName: Http::Request::ParseRequest
- >@ Brief: 解析请求参数
- >@ Access: public
- >@ Returns: bool
- >@ Qualifier:
- ************************************/
- bool ParseRequest();
- rest_query_t* GetQuery(void){return _query;}
- private:
- rest_query_t _query[QUERY_MAX_SIZE];//请求参数
- HTTP_METHOD method;
- struct soap* soap;
- CRestServicePlugin * _plugin;
- };
- #define RESPONSE_MODE_SYN 0 //同步
- #define RESPONSE_MODE_ASYN 1 //异步
- class Response
- {
- public:
- Response(Request& req, int mod=RESPONSE_MODE_SYN);
- Response();
- ~Response();
- /** @fn SetContentType
- * @brief 设置响应内容,默认为空,例如"text/json"
- * @param
- * @return
- */
- void SetContentType(const char* conttype);
- /** @fn Send
- * @brief 发送响应数据,可以调用多次发送
- * @param
- * @return 0-发送成功
- */
- int Send(const char* data);
- int Send(const char* data, std::size_t len);
- /** @fn BeginResponse
- * @brief 开始响应
- * @param mod:响应模式,RESPONSE_MODE_SYN-同步,RESPONSE_MODE_ASYN-异步
- * @return
- */
- int BeginResponse(Request& req, int mod=RESPONSE_MODE_SYN);
- int EndResponse(void);
- protected:
- private:
- struct soap * _soap;
- int _mod;
- CRestServicePlugin *_plugin;
- };
- class CRestServicePlugin
- {
- friend class Response;
- public:
- CRestServicePlugin(void);
- ~CRestServicePlugin(void);
- static int http_get_handler(struct soap*);
- static int http_post_text_handler(struct soap *soap);
- public:
- bool Hook(struct soap* soap);
- void RegisteURI(const char* URI,RequestProcessFunc fun, void* user);
- void RegisteURI(const char* URI, RequestProcessFunction & fun);
- void UnRegisteURI(const char* URI);
- void ClearURI();
- void RegisterFreeSoap(FreeSoapFunction & fun);
- protected:
- int Process(struct soap* soap,HTTP_METHOD method);
- private:
- std::mutex m_dataMt;
- //uri的处理函数映射表
- std::map<std::size_t,RequestProcessFunction> m_uriFunMap;
- FreeSoapFunction _funFreeSoap;
- };
- }
- #endif // RestServicePlugin_CEDAF949_DFA9_4D71_95EE_8EE7A7B2BAAB_H__
- 7.插件cpp文件
- #include "RestServicePlugin.h"
- #include "httpget.h"
- namespace Http
- {
- static const char* json_type = "application/json";
- static const char* http_unknow = "HTTP/1.1 -1 UNKNOW\r\nConnection: close\r\n\r\n";
- static const char* http_400 = "HTTP/1.1 400 BAD REQUEST\r\nConnection: close\r\n\r\n";
- static const char* http_404 = "HTTP/1.1 404 NOT FOUND\r\nConnection: close\r\n\r\n";
- static const char* http_500 = "HTTP/1.1 500 SERVER ERROR\r\nConnection: close\r\n\r\n";
- //FNV hash copy from gcc
- // Dummy generic implementation (for sizeof(size_t) != 4, 8).
- template<std::size_t = sizeof(std::size_t)>
- struct Fnv_hash
- {
- static std::size_t
- hash(const char* first, std::size_t length)
- {
- std::size_t result = ;
- for (; length > ; --length)
- result = (result * ) + *first++;
- return result;
- }
- };
- template<>
- struct Fnv_hash<>
- {
- static std::size_t
- hash(const char* first, std::size_t length)
- {
- std::size_t result = static_cast<std::size_t>(2166136261UL);
- for (; length > ; --length)
- {
- result ^= (std::size_t)*first++;
- result *= 16777619UL;
- }
- return result;
- }
- };
- template<>
- struct Fnv_hash<>
- {
- static std::size_t
- hash(const char* first, std::size_t length)
- {
- std::size_t result = static_cast<std::size_t>(14695981039346656037ULL);
- for (; length > ; --length)
- {
- result ^= (std::size_t)*first++;
- result *= 1099511628211ULL;
- }
- return result;
- }
- };
- http_post_handlers handlers[] =
- {
- { "POST", Http::CRestServicePlugin::http_post_text_handler },
- { NULL }
- };
- //////////////////////////////////////////////////////////////////////////
- //CRestServicePlugin
- CRestServicePlugin::CRestServicePlugin(void)
- {
- }
- CRestServicePlugin::~CRestServicePlugin(void)
- {
- }
- bool CRestServicePlugin::Hook( struct soap* soap )
- {
- if (NULL == soap)
- {
- return false;
- }
- soap->user = (void*)this;
- soap_register_plugin_arg(soap, http_get, (void*)http_get_handler);
- soap_register_plugin_arg(soap,http_post,(void*)handlers);
- return true;
- }
- void CRestServicePlugin::RegisteURI( const char* URI,RequestProcessFunc fun , void* user)
- {
- std::tr1::function<int(Request& request)> funl;
- funl = std::tr1::bind(fun, std::tr1::placeholders::_1, user);
- RegisteURI(URI, funl);
- }
- void CRestServicePlugin::RegisteURI(const char* URI, RequestProcessFunction & fun)
- {
- size_t hash_uri = Fnv_hash<>::hash(URI, strlen(URI));
- std::lock_guard<std::mutex> guard(m_dataMt);
- std::map<size_t, RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
- if (iter != m_uriFunMap.end())
- {
- iter->second = fun;
- }
- else
- {
- m_uriFunMap.insert(std::map<size_t,RequestProcessFunction>::value_type(hash_uri,fun));
- }
- }
- void CRestServicePlugin::RegisterFreeSoap(FreeSoapFunction & fun)
- {
- _funFreeSoap = fun;
- }
- void CRestServicePlugin::UnRegisteURI( const char* URI )
- {
- size_t hash_uri = Fnv_hash<>::hash(URI, strlen(URI));
- std::lock_guard<std::mutex> guard(m_dataMt);
- std::map<size_t,RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
- if (iter != m_uriFunMap.end())
- {
- m_uriFunMap.erase(iter);
- }
- }
- void CRestServicePlugin::ClearURI()
- {
- std::lock_guard<std::mutex> guard(m_dataMt);
- m_uriFunMap.clear();
- _funFreeSoap = NULL;
- }
- int CRestServicePlugin:: http_get_handler(struct soap* soap)
- {
- if (soap == NULL || soap->user == NULL)
- {
- return SOAP_ERR;
- }
- Http::CRestServicePlugin* pThis = (CRestServicePlugin*)soap->user;
- return pThis->Process(soap,HTTP_GET);
- }
- /* the text handler copies the message back */
- int CRestServicePlugin:: http_post_text_handler(struct soap *soap)
- {
- if (soap == NULL || soap->user == NULL)
- {
- return SOAP_ERR;
- }
- Http::CRestServicePlugin* pThis = (CRestServicePlugin*)soap->user;
- return pThis->Process(soap,HTTP_POST);
- }
- int CRestServicePlugin::Process( struct soap* soap ,HTTP_METHOD method)
- {
- Request request;
- request.method = method;
- request.soap = soap;
- request._plugin = this;
- std::tr1::function<int(Request& request)> *fun = NULL;
- {
- char* uri = query(soap);
- size_t hash_uri = Fnv_hash<>::hash(soap->path, uri? (uri-soap->path): strlen(soap->path));
- std::lock_guard<std::mutex> guard(m_dataMt);
- std::map<size_t,RequestProcessFunction>::iterator iter = m_uriFunMap.find(hash_uri);
- if (iter != m_uriFunMap.end())
- {
- fun = &iter->second;
- }
- }
- if(!request.ParseRequest() || fun==NULL)
- {
- return request.ReponseWithEnd(HTTP_STATUS_NOT_FOUND);
- }
- return (*fun)(request);
- }
- //////////////////////////////////////////////////////////////////////////
- //Request
- const char* Request::GetURI( )
- {
- return soap->path;
- }
- bool Request::ParseRequest()
- {
- char *s;
- s = query(soap);
- int i = ;
- while (s && s[] != '\0' && i<QUERY_MAX_SIZE)
- {
- char *key = query_key(soap,&s);
- if (key == NULL)
- {
- continue;
- }
- char* val = query_val(soap,&s);
- if (val == NULL)
- {
- continue;
- }
- _query[i].key = key;
- _query[i].value = val;
- ++i;
- }
- if (i<QUERY_MAX_SIZE)
- {//最后一个初始化为空
- _query[i].key = NULL;
- }
- return true;
- }
- const char* Request::Query( const char* key)
- {
- if (key == NULL)
- {
- return NULL;
- }
- int i = ;
- while (i<QUERY_MAX_SIZE && _query[i].key!=NULL)
- {
- if (strcmp(_query[i].key, key) == )
- {
- return _query[i].value;
- }
- ++i;
- }
- return NULL;
- }
- int Request::ReponseWithEnd( int code )
- {
- const char* res = NULL;
- switch(code)
- {
- case HTTP_STATUS_BAD_REQUEST:
- res = http_400;
- break;
- case HTTP_STATUS_NOT_FOUND:
- res = http_404;
- break;
- case HTTP_STATUS_SERVER_ERROR:
- res = http_500;
- break;
- default:
- res = http_unknow;
- break;
- }
- soap_send(soap,res);
- soap_end_send(soap);
- return SOAP_OK;
- }
- size_t Request::GetBody(char** body )
- {
- size_t len = ;
- if(SOAP_OK != soap_http_body(soap, body, &len))
- {
- return ;
- }
- return len;
- }
- //////////////////////////////////////////////////////////////////////////
- //response
- Response::Response()
- {
- _soap = NULL;
- _mod = RESPONSE_MODE_SYN;
- //soap->user = RESPONSE_MODE_SYN;
- _plugin = NULL;
- }
- Response::Response(Request& req, int mod)
- {
- _soap = NULL;
- BeginResponse(req, mod);
- }
- Response::~Response()
- {
- EndResponse();
- }
- void Response::SetContentType(const char* conttype)
- {
- _soap->http_content = conttype;
- }
- int Response::Send(const char* data)
- {
- return Send(data, strlen(data));
- }
- int Response::Send(const char* data, std::size_t len)
- {
- return soap_send_raw(_soap, data, len);
- }
- int Response::BeginResponse(Request& req, int mod)
- {
- EndResponse();
- _soap = req.soap;
- _mod = mod;
- _soap->user = (void*)_mod;
- _plugin = req._plugin;
- return soap_response(_soap ,SOAP_FILE);
- }
- int Response::EndResponse(void)
- {
- int ret = SOAP_OK;
- if (_soap == NULL)
- {
- return SOAP_OK;
- }
- ret = soap_end_send(_soap);
- if (_mod == RESPONSE_MODE_ASYN)
- {//如果是异步模式,需要释放
- soap_destroy(_soap);
- soap_end(_soap);
- if (_plugin->_funFreeSoap)
- {
- _plugin->_funFreeSoap(_soap);
- }
- else
- {
- soap_done(_soap);
- soap_free(_soap);
- }
- }
- _soap = NULL;
- _mod = RESPONSE_MODE_SYN;
- _plugin = NULL;
- return ret;
- }
- }//namespace Http
- 8.使用例子
- #include "./web/SoapWebServer.h"
- #include "cJSON.h"
- #include <thread>
- bool static copy_file(Response* res, const char *name)
- {
- FILE *fd;
- size_t r;
- fd = fopen(name, "rb"); /* open file to copy */
- if (!fd)
- return false; /* return HTTP not found */
- int tmpbuf_len = ;
- char *tmpbuf = new char[tmpbuf_len];
- for (;;)
- {
- r = fread(tmpbuf, , tmpbuf_len, fd);
- if (!r)
- break;
- if (res->Send(tmpbuf, r))
- {//发送失败
- fclose(fd);
- return false;
- }
- //Sleep(70);
- }
- delete []tmpbuf;
- fclose(fd);
- return true;
- }
- void ThreadResponseImg(Response* res)
- {
- bool bret = false;
- res->SetContentType("image/jpeg");
- bret = copy_file(res, "E:\\test\\testimage\\v1.jpg");
- //printf("发送文件 %s\n", bret?"成功":"失败");
- delete res;
- }
- static int api_login(Request &req, void *user)
- {
- char * body = NULL;
- if (req.GetBody(&body))
- {
- printf("request login=%s\n", body);
- }
- cJSON *jsonRes = NULL;
- jsonRes = cJSON_CreateObject();
- cJSON_AddNumberToObject(jsonRes, "errorCode", );
- cJSON_AddStringToObject(jsonRes, "token", "fd90bba04662411f86d8936900131936");
- char * str = cJSON_Print(jsonRes);
- Response resp(req);
- resp.Send(str);
- cJSON_Delete(jsonRes);
- free(str);
- return ;
- }
- class print_json
- {
- public:
- print_json()
- {
- //printf("cons print_json \n");
- }
- ~print_json()
- {
- printf("des print_json\n");
- }
- int print_person(Request &req)
- {
- Response res(req);
- res.SetContentType("application/json; charset=utf-8");
- res.Send("{\"print_person\" : 10}");
- return ;
- }
- int print_query(Request &req)
- {
- Response res(req);
- res.SetContentType("application/json; charset=utf-8");
- res.Send("{\"print_query\" : 10}");
- /*for (rest_query_t *q = req.GetQuery(); q->key; ++q)
- {
- printf("key-%s,val-%s", q->key, q->value);
- }*/
- printf("\n");
- return ;
- }
- int print_img(Request &req)
- {
- Response *res = new Response;
- res->BeginResponse(req, RESPONSE_MODE_SYN);
- ThreadResponseImg(res); //同步
- //这里可以开启线程进行异步发送RESPONSE_MODE_ASYN
- //std::thread t1(ThreadResponseImg, res);
- //t1.detach();
- return ;
- }
- protected:
- private:
- };
- int main(int argc, char* argv[])
- {
- print_json pt;
- CSoapWebServer web;
- const char* host = "0.0.0.0";
- unsigned port = ;
- web.StartService(host, port);
- printf("start listen %s:%u\n", host, port);
- //tr1 bug 不能把bind作为参数传递
- //web.SetURI("/json", std::tr1::bind(&print_json::print, &pt, std::tr1::placeholders::_1));
- web.SetURI("/json", (RequestProcessFunction)std::tr1::bind(
- &print_json::print_person, &pt, std::tr1::placeholders::_1));
- web.SetURI("/json1", (RequestProcessFunction)std::tr1::bind(
- &print_json::print_query, &pt, std::tr1::placeholders::_1));
- web.SetURI("/img", (RequestProcessFunction)std::tr1::bind(
- &print_json::print_img, &pt, std::tr1::placeholders::_1));
- web.SetURI("/login", api_login, NULL);
- getchar();
- web.StopService();
- return ;
- }
在浏览器中访问接口:
http://127.0.0.1:56789/json
这个接口返回json内容:
{"print_person" : 10}
http://127.0.0.1:56789/img
这个接口返回的是一张图片
利用gsoap库封装易用的rest框架的更多相关文章
- 人脸检测及识别python实现系列(5)——利用keras库训练人脸识别模型
人脸检测及识别python实现系列(5)——利用keras库训练人脸识别模型 经过前面稍显罗嗦的准备工作,现在,我们终于可以尝试训练我们自己的卷积神经网络模型了.CNN擅长图像处理,keras库的te ...
- c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)
c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...
- php学习笔记:利用gd库生成图片,并实现随机验证码
说明:一些基本的代码我都进行了注释,这里实现的验证码位数.需要用的字符串都可以再设置.有我的注释,大家应该很容易能看得懂. 基本思路: 1.用mt_rand()随机生成数字确定需要获取的字符串,对字符 ...
- CocoaPods的安装及使用/利用开源库Diplomat实现分享及第三方登录/git的使用
<<史上最简洁版本>> 1.gem sources -l查看 当前的源 //1.1 sudo -i..以下都是以管理员的身份来操作的 2.gem sources --remov ...
- 使用libzplay库封装一个音频类
装载请说明原地址,谢谢~~ 前两天我已经封装好一个duilib中使用的webkit内核的浏览器控件和一个基于vlc的用于播放视频的视频控件,这两个控件可以分别用在放酷狗播放器的乐库功能和MV ...
- 利用jdbc简单封装一个小框架(类似DBUtils)
利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...
- python利用selenium库识别点触验证码
利用selenium库和超级鹰识别点触验证码(学习于静谧大大的书,想自己整理一下思路) 一.超级鹰注册:超级鹰入口 1.首先注册一个超级鹰账号,然后在超级鹰免费测试地方可以关注公众号,领取1000积分 ...
- 利用OpenSSL库对Socket传输进行安全加密(RSA+AES)
轉自:http://blog.chinaunix.net/uid-9543173-id-3921143.html 利用OpenSSL库对Socket传输进行安全加密(RSA+AES) 1. 利用RSA ...
- python3:利用smtplib库和smtp.qq.com邮件服务器发送邮件
python3:利用smtplib库和smtp.qq.com邮件服务器发送邮件 使用qq的邮件服务器需要注意的两个地方主要是: 1.协议问题 使用465端口 SSL 协议 2.口令问题 出现SMTPA ...
随机推荐
- JTabbedPane的LookAndFeel--TabbedPaneUI
在定制JTabbedPane的时候是需要使用到LookAndFeel的,而使用LookAndFeel定制的时候,其实主要是继承BasicTabbedPaneUI. to be continue...
- su 认证失败
jiqing@ThinkPad:~$ su 密码: su:认证失败 jiqing@ThinkPad:~$ sudo passwd root [sudo] password for jiqing: 输入 ...
- securecrt中vim行号下划线问题及SecureCRT里root没有高亮的设置,修改linux终端命令行颜色
背景:在用raspberry用SecureCRT下的vim打开文件时出现用set nu时行有下划线,于是找了下解决办法,如下:vim行号下划线问题在vim中发现开启显示行号(set number) ...
- pycharm打开多个项目并存
问题: 有时我们需要打开多个项目,而现在的做法是: 原有的a项目不动,新打开一个pycharm来打开b项目, 或者 在原有的a项目中打开b项目并覆盖a项目,即a项目与b项目不能共存 需求: 有时我们 ...
- GitLab: API is not accessibl
git push -u origin masterGitLab: API is not accessiblefatal: Could not read from remote repository. ...
- Python基础 — OS
OS模块 -- 简介 OS模块是Python标准库中的一个用于访问操作系统功能的模块,OS模块提供了一种可移植的方法使用操作系统的功能.使用OS模块中提供的接口,可以实现跨平台访问.但是在OS模块 ...
- git clone ssh permissions are too open 解决方案。
错误如图所示 方案如下 https://stackoverflow.com/questions/9270734/ssh-permissions-are-too-open-error
- NET 编程题
1.C#编写创建一个线程的代码 using System; using System.IO; using System.Threading ; class MyThread{ public int c ...
- 使用JS分页 <span> beta 3.0 完成封装的分页
<html> <head> <title>分页</title> <style> #titleDiv{ width:500px; backgr ...
- SparkContext, map, flatMap, zip以及例程wordcount
SparkContext 通常作为入口函数,可以创建并返回一个RDD. 如把Spark集群当作服务端那Spark Driver就是客户端,SparkContext则是客户端的核心: 如注释所说 Spa ...