Botan  2.1.0
Crypto and TLS for C++11
Classes | Typedefs | Functions
Botan::HTTP Namespace Reference

Classes

struct  HTTP_Error
 
struct  Response
 

Typedefs

typedef std::function< std::string(const std::string &, const std::string &)> http_exch_fn
 

Functions

Response GET_sync (const std::string &url, size_t allowable_redirects)
 
Response http_sync (http_exch_fn http_transact, const std::string &verb, const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
 
Response http_sync (const std::string &verb, const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
 
std::ostream & operator<< (std::ostream &o, const Response &resp)
 
Response POST_sync (const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
 
std::string url_encode (const std::string &in)
 

Typedef Documentation

typedef std::function<std::string (const std::string&, const std::string&)> Botan::HTTP::http_exch_fn

Definition at line 68 of file http_util.h.

Function Documentation

BOTAN_DLL Response Botan::HTTP::GET_sync ( const std::string &  url,
size_t  allowable_redirects 
)

Definition at line 289 of file http_util.cpp.

References http_sync().

Referenced by http_sync().

290  {
291  return http_sync("GET", url, "", std::vector<uint8_t>(), allowable_redirects);
292  }
Response http_sync(const std::string &verb, const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
Definition: http_util.cpp:274
BOTAN_DLL Response Botan::HTTP::http_sync ( http_exch_fn  http_transact,
const std::string &  verb,
const std::string &  url,
const std::string &  content_type,
const std::vector< uint8_t > &  body,
size_t  allowable_redirects 
)

Definition at line 165 of file http_util.cpp.

References GET_sync(), Botan::search_map(), Botan::ASN1::to_string(), and Botan::to_u32bit().

Referenced by GET_sync(), http_sync(), and POST_sync().

171  {
172  if(url.empty())
173  throw HTTP_Error("URL empty");
174 
175  const auto protocol_host_sep = url.find("://");
176  if(protocol_host_sep == std::string::npos)
177  throw HTTP_Error("Invalid URL '" + url + "'");
178 
179  const auto host_loc_sep = url.find('/', protocol_host_sep + 3);
180 
181  std::string hostname, loc;
182 
183  if(host_loc_sep == std::string::npos)
184  {
185  hostname = url.substr(protocol_host_sep + 3, std::string::npos);
186  loc = "/";
187  }
188  else
189  {
190  hostname = url.substr(protocol_host_sep + 3, host_loc_sep-protocol_host_sep-3);
191  loc = url.substr(host_loc_sep, std::string::npos);
192  }
193 
194  std::ostringstream outbuf;
195 
196  outbuf << verb << " " << loc << " HTTP/1.0\r\n";
197  outbuf << "Host: " << hostname << "\r\n";
198 
199  if(verb == "GET")
200  {
201  outbuf << "Accept: */*\r\n";
202  outbuf << "Cache-Control: no-cache\r\n";
203  }
204  else if(verb == "POST")
205  outbuf << "Content-Length: " << body.size() << "\r\n";
206 
207  if(!content_type.empty())
208  outbuf << "Content-Type: " << content_type << "\r\n";
209  outbuf << "Connection: close\r\n\r\n";
210  outbuf.write(reinterpret_cast<const char*>(body.data()), body.size());
211 
212  std::istringstream io(http_transact(hostname, outbuf.str()));
213 
214  std::string line1;
215  std::getline(io, line1);
216  if(!io || line1.empty())
217  throw HTTP_Error("No response");
218 
219  std::stringstream response_stream(line1);
220  std::string http_version;
221  unsigned int status_code;
222  std::string status_message;
223 
224  response_stream >> http_version >> status_code;
225 
226  std::getline(response_stream, status_message);
227 
228  if(!response_stream || http_version.substr(0,5) != "HTTP/")
229  throw HTTP_Error("Not an HTTP response");
230 
231  std::map<std::string, std::string> headers;
232  std::string header_line;
233  while (std::getline(io, header_line) && header_line != "\r")
234  {
235  auto sep = header_line.find(": ");
236  if(sep == std::string::npos || sep > header_line.size() - 2)
237  throw HTTP_Error("Invalid HTTP header " + header_line);
238  const std::string key = header_line.substr(0, sep);
239 
240  if(sep + 2 < header_line.size() - 1)
241  {
242  const std::string val = header_line.substr(sep + 2, (header_line.size() - 1) - (sep + 2));
243  headers[key] = val;
244  }
245  }
246 
247  if(status_code == 301 && headers.count("Location"))
248  {
249  if(allowable_redirects == 0)
250  throw HTTP_Error("HTTP redirection count exceeded");
251  return GET_sync(headers["Location"], allowable_redirects - 1);
252  }
253 
254  std::vector<uint8_t> resp_body;
255  std::vector<uint8_t> buf(4096);
256  while(io.good())
257  {
258  io.read(reinterpret_cast<char*>(buf.data()), buf.size());
259  resp_body.insert(resp_body.end(), buf.data(), &buf[io.gcount()]);
260  }
261 
262  const std::string header_size = search_map(headers, std::string("Content-Length"));
263 
264  if(!header_size.empty())
265  {
266  if(resp_body.size() != to_u32bit(header_size))
267  throw HTTP_Error("Content-Length disagreement, header says " +
268  header_size + " got " + std::to_string(resp_body.size()));
269  }
270 
271  return Response(status_code, status_message, resp_body, headers);
272  }
uint32_t to_u32bit(const std::string &str)
Definition: parsing.cpp:18
V search_map(const std::map< K, V > &mapping, const K &key, const V &null_result=V())
Definition: stl_util.h:52
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:47
Response GET_sync(const std::string &url, size_t allowable_redirects)
Definition: http_util.cpp:289
BOTAN_DLL Response Botan::HTTP::http_sync ( const std::string &  verb,
const std::string &  url,
const std::string &  content_type,
const std::vector< uint8_t > &  body,
size_t  allowable_redirects 
)

Definition at line 274 of file http_util.cpp.

References http_sync().

279  {
280  return http_sync(
281  http_transact,
282  verb,
283  url,
284  content_type,
285  body,
286  allowable_redirects);
287  }
Response http_sync(const std::string &verb, const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
Definition: http_util.cpp:274
BOTAN_DLL std::ostream & Botan::HTTP::operator<< ( std::ostream &  o,
const Response resp 
)

Definition at line 155 of file http_util.cpp.

References Botan::HTTP::Response::body(), Botan::HTTP::Response::headers(), Botan::HTTP::Response::status_code(), Botan::HTTP::Response::status_message(), and Botan::ASN1::to_string().

156  {
157  o << "HTTP " << resp.status_code() << " " << resp.status_message() << "\n";
158  for(auto h : resp.headers())
159  o << "Header '" << h.first << "' = '" << h.second << "'\n";
160  o << "Body " << std::to_string(resp.body().size()) << " bytes:\n";
161  o.write(reinterpret_cast<const char*>(&resp.body()[0]), resp.body().size());
162  return o;
163  }
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:47
BOTAN_DLL Response Botan::HTTP::POST_sync ( const std::string &  url,
const std::string &  content_type,
const std::vector< uint8_t > &  body,
size_t  allowable_redirects 
)

Definition at line 294 of file http_util.cpp.

References http_sync().

298  {
299  return http_sync("POST", url, content_type, body, allowable_redirects);
300  }
Response http_sync(const std::string &verb, const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
Definition: http_util.cpp:274
BOTAN_DLL std::string Botan::HTTP::url_encode ( const std::string &  in)

Definition at line 134 of file http_util.cpp.

135  {
136  std::ostringstream out;
137 
138  for(auto c : in)
139  {
140  if(c >= 'A' && c <= 'Z')
141  out << c;
142  else if(c >= 'a' && c <= 'z')
143  out << c;
144  else if(c >= '0' && c <= '9')
145  out << c;
146  else if(c == '-' || c == '_' || c == '.' || c == '~')
147  out << c;
148  else
149  out << '%' << hex_encode(reinterpret_cast<uint8_t*>(&c), 1);
150  }
151 
152  return out.str();
153  }