diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-08-25 16:56:56 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-09-24 16:12:03 +0200 |
commit | b94635f70430c3659cd57596e49649d376284473 (patch) | |
tree | 8d3957bf7c26c8fffeb7f961e0826ab625d5052a /common | |
parent | 28446bed24689b2bac7c8bfbd37741a7fa4fa6be (diff) | |
download | qtlocation-mapboxgl-b94635f70430c3659cd57596e49649d376284473.tar.gz |
parse cache-control and last-modified headers
Diffstat (limited to 'common')
-rw-r--r-- | common/curl_request.cpp | 31 | ||||
-rw-r--r-- | common/foundation_request.mm | 4 |
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]; } |