| 820 | |
| 821 | #if !defined(DM_NO_HTTP_CACHE) |
| 822 | static Result HandleCached(HClient client, const char* path, Response* response, bool method_is_head) |
| 823 | { |
| 824 | client->m_Statistics.m_CachedResponses++; |
| 825 | if (client->m_IgnoreCache) |
| 826 | { |
| 827 | return RESULT_OK; |
| 828 | } |
| 829 | |
| 830 | if (client->m_HttpCache == 0) |
| 831 | { |
| 832 | dmLogWarning("Got HTTP response NOT MODIFIED (304) but no cache present"); |
| 833 | return RESULT_OK; |
| 834 | } |
| 835 | dmHttpCache::Result cache_result; |
| 836 | |
| 837 | char cache_etag[dmHttpCache::MAX_TAG_LEN]; |
| 838 | cache_etag[0] = '\0'; |
| 839 | cache_result = dmHttpCache::GetETag(client->m_HttpCache, client->m_CacheKey, cache_etag, sizeof(cache_etag)); |
| 840 | |
| 841 | if (cache_result != dmHttpCache::RESULT_OK) |
| 842 | { |
| 843 | dmLogWarning("Got HTTP response NOT MODIFIED (304) but no ETag present. Returning no cached data."); |
| 844 | return RESULT_OK; |
| 845 | } |
| 846 | |
| 847 | if (response->m_ETag[0] != '\0') |
| 848 | { |
| 849 | // The Entity Tag (ETag) is optional in HTTP 1.1. |
| 850 | // It is the servers responsibility to verify the ETag in case it is included. The |
| 851 | // ETag is a mechanism to reduce the bandwidth required by the server, not |
| 852 | // by the client. There is no guarantee that an ETag will be included in a |
| 853 | // 403 response even though it's been sent with a previous 200 response. |
| 854 | // Even though it might be possible at times, the client has no formal responsibility |
| 855 | // to perform this verification. |
| 856 | if (strcmp(cache_etag, response->m_ETag) != 0) |
| 857 | { |
| 858 | dmLogError("ETag mismatch (%s vs %s)", cache_etag, response->m_ETag); |
| 859 | return RESULT_IO_ERROR; |
| 860 | } |
| 861 | } |
| 862 | |
| 863 | FILE* file = 0; |
| 864 | uint32_t file_size = 0; |
| 865 | uint64_t checksum; |
| 866 | uint32_t range_start; |
| 867 | uint32_t range_end; |
| 868 | uint32_t document_size; |
| 869 | cache_result = dmHttpCache::Get(client->m_HttpCache, client->m_CacheKey, cache_etag, &file, &file_size, &checksum, |
| 870 | &range_start, &range_end, &document_size); |
| 871 | if (cache_result == dmHttpCache::RESULT_OK) |
| 872 | { |
| 873 | // If the request is a "HEAD" request, and the URI is cached (i.e the file exists), |
| 874 | // then we should return the meta-data about the file (including triggering the progress callback). |
| 875 | if (method_is_head) |
| 876 | { |
| 877 | client->m_HttpContent(response, client->m_Userdata, response->m_Status, 0, 0, file_size, |
| 878 | range_start, range_end, document_size, |
| 879 | "HEAD"); |
no test coverage detected