26 #include "third_party/mongoose/mongoose.h"
34 static std::string BuildRangeRequestHeader(int64 start, int64 end) {
35 std::stringstream headers;
36 headers <<
"Range: bytes=" << start <<
"-" << end <<
"\r\n\r\n";
40 static std::string BuildUploadHeaders(
const std::string& data) {
41 std::stringstream headers;
42 headers <<
"Content-Type: text/plain\r\n";
43 headers <<
"Content-Length: " << data.size() <<
"\r\n\r\n";
49 static std::string BuildUri(
const HttpClient::Url& url) {
50 typedef std::map<std::string, std::string>::const_iterator iterator;
51 std::string uri = url.path;
52 if (url.args.size()) {
54 for (iterator it = url.args.begin(); it != url.args.end(); ++it) {
55 if (it != url.args.begin())
57 uri.append(it->first);
59 uri.append(it->second);
65 static const HttpClient::Response SendRequest(
const HttpClient::Url& url,
67 const std::string& headers) {
68 HttpClient::Response response;
71 static const int kErrorStringLength = 2048;
72 char error[kErrorStringLength];
73 std::ostringstream header_str;
74 header_str << headers;
75 header_str <<
"Host: " + url.hostname <<
"\r\n";
76 const std::string header_string = header_str.str();
79 if (mg_connection* connection = mg_download(url.hostname.c_str(),
84 "%s %s HTTP/1.1\r\n%s\r\n",
86 BuildUri(url).c_str(),
87 header_string.c_str())) {
89 mg_request_info* info = mg_get_request_info(connection);
93 for (
int i = 0; i < info->num_headers; ++i) {
94 response.headers[info->http_headers[i].name] =
95 info->http_headers[i].value;
98 static const int kBufferSize = 512;
99 char buf[kBufferSize];
101 response.data.reserve(kBufferSize);
103 while ((bytes_read = mg_read(connection, buf,
sizeof(buf))) > 0) {
104 response.data.insert(response.data.end(), buf, &buf[bytes_read]);
106 mg_close_connection(connection);
122 typedef std::string::const_iterator iterator;
134 iterator end = url.end();
137 iterator query_pos = std::find(url.begin(), end,
'?');
140 iterator proto_start = url.begin();
141 iterator proto_end = std::find(proto_start, end,
':');
143 if (proto_end != end) {
144 const std::string prot = &*(proto_end);
145 if ((prot.length() > 3) && (prot.substr(0, 3) ==
"://")) {
146 const std::string protocol(proto_start, proto_end);
147 if (protocol ==
"https") {
150 }
else if (protocol !=
"http") {
151 LOG(
ERROR) <<
"Unknown protocol '" << protocol
152 <<
"', defaulting to http";
157 proto_end = url.begin();
161 proto_end = url.begin();
166 iterator host_start = proto_end;
167 iterator path_start = std::find(host_start, end,
'/');
171 std::find(proto_end, (path_start != end) ? path_start : query_pos,
':');
173 hostname = std::string(host_start, hostEnd);
176 if ((hostEnd != end) && ((&*(hostEnd))[0] ==
':')) {
178 iterator portEnd = (path_start != end) ? path_start : query_pos;
179 const std::string port_string(hostEnd, portEnd);
184 if (path_start != end)
185 path = std::string(path_start, query_pos);
190 if (query_pos != end) {
192 std::vector<std::string> queries =
194 const size_t num_queries = queries.size();
195 for (
size_t i = 0; i < num_queries; ++i) {
196 const std::vector<std::string> pairs =
199 DCHECK(pairs.size() == 1 || pairs.size() == 2);
200 if (pairs.size() > 1)
201 args[pairs[0]] = pairs[1];
209 return port > 0 && !hostname.empty();
222 return SendRequest(
Url(url),
"GET",
"");
226 const std::string& url, int64 start, int64 end)
const {
227 return SendRequest(
Url(url),
"GET", BuildRangeRequestHeader(start, end));
231 return SendRequest(
Url(url),
"HEAD",
"");
235 const std::string& data) {
236 return SendRequest(
Url(url),
"POST", BuildUploadHeaders(data));
240 const std::string& data) {
241 return SendRequest(
Url(url),
"PUT", BuildUploadHeaders(data));
virtual const Response Head(const std::string &url) const
Sends a HEAD request for a URL and returns the remote host's response.
Simple wrapper around a URL.
virtual const Response GetRange(const std::string &url, int64 start, int64 end) const
Sends a GET request for the passed byte range and returns the remote host's response.
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
virtual const Response Put(const std::string &url, const std::string &data)
PUTs data to URL and returns the remote host's response.
virtual const Response Get(const std::string &url) const
Sends a GET request for a URL and returns the remote host's response.
Url()
Constructs an empty, invalid Url.
std::vector< std::string > ION_API SplitString(const std::string &str, const std::string &delimiters)
Splits a string into a vector of substrings, given a set of delimiter characters (expressed as a stri...
int32 ION_API StringToInt32(const std::string &str)
Extracts and returns an integral value from str.
bool IsValid() const
Returns whether this Url is valid.
Copyright 2016 Google Inc.
void Set(const std::string &url)
Sets the url from the passed value.
virtual const Response Post(const std::string &url, const std::string &data)
POSTs data to URL and returns the remote host's response.