boost http请求应用

项目接近阶段性尾声了,又要去做另一个项目的框架,真是完全忙不过来。。。

整理项目过程中,为了减少第三方库的使用,我使用boost的asio封装了http请求

 1 #pragma once
 2 
 3 #include <string>
 4 #include <vector>
 5 #include <iostream>
 6 #include <boost/asio.hpp>
 7 #include <boost/enable_shared_from_this.hpp>
 8 
 9 struct header
10 {
11     std::string name;
12     std::string value;
13 };
14 
15 struct msg_request
16 {
17 public:
18     explicit msg_request(){ clear();}
19     
20     std::string method;            // "GET", "POST".    
21     std::string uri;            // 不包含http://的路径
22     int http_version_major;        // 
23     int http_version_minor;        // 
24     std::vector<header> headers;// HTTP包头
25     std::string content;        // 上传的数据
26     std::string spath;            // 请求地址
27 
28     void clear()
29     {
30         method = "GET";
31         uri.clear();
32         http_version_major = 1;
33         http_version_minor = 0;
34         headers.clear();
35         content.clear();
36         spath.clear();
37 
38     }
39 };
40 
41 struct msg_response
42 {
43 public:
44     explicit msg_response(){ clear();}    
45     std::string http_version;        // 版本
46     int32_t status_code;            // 状态码
47     std::string status_message;        // 状态
48     std::vector<header> headers;    // HTTP包头
49     std::stringstream content;        // HTTP返回的内容    
50 
51     void clear()
52     {
53         http_version.clear();
54         status_code = -1;
55         status_message.clear();
56         headers.clear();
57         content.str("");
58     }
59 };
60 
61 class peer_http: public boost::enable_shared_from_this<peer_http>
62 {
63 public:
64     peer_http(boost::asio::io_service& io_service);
65     virtual ~peer_http();
66 
67     void post_request(const msg_request& req);    
68     //同步处理才使用
69     virtual void on_complete(){};    
70 private:
71     void handle_resolve(const boost::system::error_code& err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
72     void handle_connect(const boost::system::error_code& err);
73     void handle_write_request(const boost::system::error_code& err);
74     void handle_read_status_line(const boost::system::error_code& err);
75     void handle_read_headers(const boost::system::error_code& err);
76     void handle_read_content(const boost::system::error_code& err);
77 
78 private:
79     boost::asio::ip::tcp::resolver resolver_;
80     boost::asio::ip::tcp::socket socket_;
81     boost::asio::streambuf request_;
82     boost::asio::streambuf response_;
83 
84 protected:
85     //http结果回调接口 (异步非线程安全)
86     virtual void http_response(bool result, const std::string& response) = 0;
87 
88     //同步处理 使用peer_http_mgr从on_complete处理
89     void use_synchronization();
90     msg_response m_response;
91 };
peer_http.h
  1 #include "stdafx.h"
  2 #include "peer_http.h"
  3 #include <boost/bind.hpp>
  4 #include <boost/lexical_cast.hpp>
  5 #include <boost/algorithm/string.hpp>
  6 
  7 using namespace boost;
  8 using namespace boost::asio::ip;
  9 
 10 peer_http::peer_http(boost::asio::io_service& io_service)
 11     : resolver_(io_service),
 12     socket_(io_service)
 13 {
 14 }
 15 
 16 peer_http::~peer_http()
 17 {
 18     if(socket_.is_open())
 19     {
 20         boost::system::error_code ec;
 21         socket_.close(ec);
 22     }    
 23 }
 24 
 25 void peer_http::post_request(const msg_request& req)
 26 {
 27     std::ostream request_stream(&request_);
 28     if (req.method == "GET")
 29     {
 30         request_stream << req.method <<" "<< req.spath << " HTTP/"<< req.http_version_major<<"."<<req.http_version_minor<<"\r\n";
 31         request_stream << "Host: " << req.uri << "\r\n\r\n";
 32     }        
 33     else if (req.method == "POST")
 34     {
 35         request_stream << req.method <<" "<< req.spath << " HTTP/"<< req.http_version_major<<"."<<req.http_version_minor<<"\r\n";
 36         request_stream << "Host: " << req.uri << "\r\n";
 37         request_stream << req.headers[1].name << ": "<<req.headers[1].value <<"\r\n";
 38         request_stream << req.headers[0].name << ": "<<req.headers[0].value <<"\r\n\r\n";
 39         request_stream << req.content << "\r\n\r\n";
 40     }
 41 
 42     request_stream << "Accept: */*\r\n";
 43     //request_stream << "Pragma: no-cache\r\n";
 44     //request_stream << "Cache-Control: no-cache\r\n";
 45     request_stream << "Connection: close\r\n";
 46 
 47     // Start an asynchronous resolve to translate the server and service names
 48     // into a list of endpoints.
 49     std::string szService ("http");
 50     std::string szIp = req.uri;
 51     int i = req.uri.find(":") ;
 52     if (i != -1)
 53     {
 54         szService = req.uri.substr(i+1);
 55         szIp = req.uri.substr(0, i);
 56     }
 57 
 58     m_response.clear();
 59                 
 60     // Get a list of endpoints corresponding to the server name.
 61     tcp::resolver::query query(szIp, szService);
 62     resolver_.async_resolve(query,
 63         boost::bind(&peer_http::handle_resolve, shared_from_this(),
 64         boost::asio::placeholders::error,
 65         boost::asio::placeholders::iterator));
 66 }
 67 
 68 void peer_http::handle_resolve(const boost::system::error_code& err,
 69                     tcp::resolver::iterator endpoint_iterator)
 70 {
 71     if (!err)
 72     {
 73         // Attempt a connection to each endpoint in the list until we
 74         // successfully establish a connection.
 75         boost::asio::async_connect(socket_, endpoint_iterator,
 76             boost::bind(&peer_http::handle_connect, shared_from_this(),
 77             boost::asio::placeholders::error));
 78     }
 79     else
 80     {
 81         http_response(false, err.message());        
 82     }
 83 }
 84 
 85 void peer_http::handle_connect(const boost::system::error_code& err)
 86 {
 87     if (!err)
 88     {
 89         // The connection was successful. Send the request.
 90         boost::asio::async_write(socket_, request_,
 91             boost::bind(&peer_http::handle_write_request, shared_from_this(),
 92             boost::asio::placeholders::error));
 93     }
 94     else
 95     {
 96         http_response(false, err.message());    
 97     }
 98 }
 99 
100 void peer_http::handle_write_request(const boost::system::error_code& err)
101 {
102     if (!err)
103     {
104         // Read the response status line. The response_ streambuf will
105         // automatically grow to accommodate the entire line. The growth may be
106         // limited by passing a maximum size to the streambuf constructor.
107         boost::asio::async_read_until(socket_, response_, "\r\n",
108             boost::bind(&peer_http::handle_read_status_line, shared_from_this(),
109             boost::asio::placeholders::error));
110     }
111     else
112     {
113         http_response(false, err.message());    
114     }
115 }
116 
117 void peer_http::handle_read_status_line(const boost::system::error_code& err)
118 {
119     if (!err)
120     {
121         // Check that response is OK.
122         std::istream response_stream(&response_);
123         response_stream >> m_response.http_version;
124         response_stream >> m_response.status_code;
125         std::getline(response_stream, m_response.status_message);
126         boost::trim(m_response.status_message);
127         if (!response_stream || m_response.http_version.substr(0, 5) != "HTTP/")
128         {
129             http_response(false, "Invalid response\n");
130             return;
131         }
132         if (m_response.status_code != 200)
133         {
134             std::string ret = "Response returned with status code " + lexical_cast<std::string>(m_response.status_code) ;
135             http_response(false, ret);            
136             return;
137         }
138 
139         // Read the response headers, which are terminated by a blank line.
140         boost::asio::async_read_until(socket_, response_, "\r\n\r\n",
141             boost::bind(&peer_http::handle_read_headers, shared_from_this(),
142             boost::asio::placeholders::error));
143     }
144     else
145     {
146         http_response(false, err.message());    
147     }
148 }
149 
150 void peer_http::handle_read_headers(const boost::system::error_code& err)
151 {
152     if (!err)
153     {
154         // Process the response headers.
155         std::istream response_stream(&response_);
156 
157         std::string strLine;  
158         while (std::getline(response_stream, strLine) && strLine != "\r")
159         {  
160             header h;
161             h.name = strLine.substr(0, strLine.find_first_of(":"));
162             h.value = strLine.substr(h.name.size()+1, strLine.find_first_of("\r"));
163             boost::trim(h.value);
164             m_response.headers.push_back(h);
165         }  
166 
167         // Write whatever content we already have to output.
168         if (response_.size() > 0)
169         {
170             m_response.content << &response_;
171         }
172 
173         // Start reading remaining data until EOF.
174         boost::asio::async_read(socket_, response_,
175             boost::asio::transfer_at_least(1),
176             boost::bind(&peer_http::handle_read_content, shared_from_this(),
177             boost::asio::placeholders::error));
178     }
179     else
180     {
181         http_response(false, err.message());    
182     }
183 }
184 
185 void peer_http::handle_read_content(const boost::system::error_code& err)
186 {
187     if (!err)
188     {
189         // Write all of the data that has been read so far.
190         m_response.content << &response_;
191 
192         // Continue reading remaining data until EOF.
193         boost::asio::async_read(socket_, response_,
194             boost::asio::transfer_at_least(1),
195             boost::bind(&peer_http::handle_read_content, shared_from_this(),
196             boost::asio::placeholders::error));
197     }
198     else if (err != boost::asio::error::eof)
199     {
200         http_response(false, err.message());        
201     }
202     else
203     {        
204         http_response(true, m_response.content.str());        
205     }
206 }
207 
208 #include <net/peer_http_mgr.h>
209 void peer_http::use_synchronization()
210 {
211     peer_http_mgr::instance().postTask(shared_from_this());
212 }
peer_http.cpp
 1 #pragma once
 2 #include <enable_queue.h>
 3 #include <enable_singleton.h>
 4 #include <enable_smart_ptr.h>
 5 
 6 class peer_http;
 7 class peer_http_mgr:
 8     public enable_singleton<peer_http_mgr>
 9 {
10 public:
11     peer_http_mgr();
12     virtual ~peer_http_mgr();
13 
14     void postTask(boost::shared_ptr<peer_http> task);
15     void update(double elapsed);
16 
17 private:
18     fast_safe_queue<boost::shared_ptr<peer_http>> m_complate_queue;
19 };
peer_http_mgr.h
 1 #include "stdafx.h"
 2 #include "peer_http_mgr.h"
 3 #include <net\peer_http.h>
 4 
 5 peer_http_mgr::peer_http_mgr()
 6 {
 7 }
 8 
 9 peer_http_mgr::~peer_http_mgr()
10 {
11 }
12 
13 void peer_http_mgr::postTask(boost::shared_ptr<peer_http> task)
14 {
15     m_complate_queue.push(task);
16 }
17 void peer_http_mgr::update(double elapsed)
18 {
19     boost::shared_ptr<peer_http> task;
20     while (!m_complate_queue.empty())
21     {        
22         if(m_complate_queue.pop(task))
23             task->on_complete();
24     }
25 }
peer_http_mgr.cpp

 boost也是支持gzip的 需要附加库编译,因为暂时不需要所以没加进去

posted @ 2015-07-06 13:53  飞鱼云  阅读(2736)  评论(0编辑  收藏  举报