summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-08-25 16:56:56 +0200
committerKonstantin Käfer <mail@kkaefer.com>2014-09-24 16:12:03 +0200
commitb94635f70430c3659cd57596e49649d376284473 (patch)
tree8d3957bf7c26c8fffeb7f961e0826ab625d5052a /common
parent28446bed24689b2bac7c8bfbd37741a7fa4fa6be (diff)
downloadqtlocation-mapboxgl-b94635f70430c3659cd57596e49649d376284473.tar.gz
parse cache-control and last-modified headers
Diffstat (limited to 'common')
-rw-r--r--common/curl_request.cpp31
-rw-r--r--common/foundation_request.mm4
2 files changed, 35 insertions, 0 deletions
diff --git a/common/curl_request.cpp b/common/curl_request.cpp
index 416ed90cd1..0957481226 100644
--- a/common/curl_request.cpp
+++ b/common/curl_request.cpp
@@ -286,6 +286,35 @@ size_t curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) {
return size * nmemb;
}
+// Compares the beginning of the (non-zero-terminated!) data buffer with the (zero-terminated!)
+// header string. If the data buffer contains the header string at the beginning, it returns
+// the length of the header string == begin of the value, otherwise it returns npos.
+// The comparison of the header is ASCII-case-insensitive.
+size_t header_matches(const char *header, const char *buffer, size_t length) {
+ const size_t header_length = strlen(header);
+ if (length < header_length) return std::string::npos;
+ size_t i = 0;
+ while (i < length && i < header_length && std::tolower(buffer[i]) == header[i]) {
+ i++;
+ }
+ return i == header_length ? i : std::string::npos;
+}
+
+size_t curl_header_cb(char *buffer, size_t size, size_t nmemb, void *userp) {
+ const size_t length = size * nmemb;
+
+ size_t begin = std::string::npos;
+ if ((begin = header_matches("last-modified: ", buffer, length)) != std::string::npos) {
+ const std::string value { buffer + begin, length - begin - 2 /* remove \r\n */ };
+ static_cast<Response *>(userp)->setLastModified(value.c_str());
+ } else if ((begin = header_matches("cache-control: ", buffer, length)) != std::string::npos) {
+ const std::string value { buffer + begin, length - begin - 2 /* remove \r\n */ };
+ static_cast<Response *>(userp)->setCacheControl(value.c_str());
+ }
+
+ return length;
+}
+
// This callback is called in the request event loop (on the request thread).
// It initializes newly queued up download requests and adds them to the CURL
// multi handle.
@@ -315,6 +344,8 @@ void async_add_cb(uv_async_t * /*async*/) {
curl_easy_setopt(handle, CURLOPT_URL, (*req)->url.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curl_write_cb);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &(*req)->res->body);
+ curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, curl_header_cb);
+ curl_easy_setopt(handle, CURLOPT_HEADERDATA, (*req)->res.get());
curl_easy_setopt(handle, CURLOPT_ACCEPT_ENCODING, "gzip, deflate");
curl_easy_setopt(handle, CURLOPT_SHARE, curl_share);
curl_multi_add_handle(curl_multi, handle);
diff --git a/common/foundation_request.mm b/common/foundation_request.mm
index b7eafdb96c..478dadf4d9 100644
--- a/common/foundation_request.mm
+++ b/common/foundation_request.mm
@@ -91,8 +91,12 @@ mbgl::platform::request_http(const std::string &url,
}
if (!error && [response isKindOfClass:[NSHTTPURLResponse class]]) {
+ NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields];
(*req_ptr)->res->code = [(NSHTTPURLResponse *)response statusCode];
(*req_ptr)->res->body = {(const char *)[data bytes], [data length]};
+ (*req_ptr)->res->setCacheControl([[headers objectForKey:@"Cache-Control"] UTF8String]);
+ (*req_ptr)->res->setLastModified([[headers objectForKey:@"Last-Modified"] UTF8String]);
+
} else {
(*req_ptr)->res->error_message = [[error localizedDescription] UTF8String];
}