[rp-download] Set an "Accept:" header for the expected MIME type.
Some checks failed
Codecov / run (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled

Expected MIME types:
- .png: image/png
- .jpg: image/jpeg
- .txt: text/plain

Not sure if this will make any real difference, but we might as well
set it anyway.
This commit is contained in:
David Korth 2025-05-17 13:17:45 -04:00
parent 05f08c2d32
commit 55cb219a17
5 changed files with 114 additions and 5 deletions

View File

@ -195,6 +195,21 @@ int CurlDownloader::download(void)
curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
}
// Custom headers
struct curl_slist *req_headers = nullptr;
if (!m_reqMimeType.empty()) {
// Add the "Accept:" header.
tstring accept_header = _T("Accept: ");
accept_header += m_reqMimeType;
req_headers = curl_slist_append(req_headers, accept_header.c_str());
}
if (req_headers) {
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, req_headers);
}
// Header and data functions.
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, this);
@ -254,6 +269,7 @@ int CurlDownloader::download(void)
break;
}
curl_slist_free_all(req_headers);
curl_easy_cleanup(curl);
if (ret != 0) {
return ret;

View File

@ -138,6 +138,37 @@ void IDownloader::setIfModifiedSince(time_t timestamp)
m_if_modified_since = timestamp;
}
/**
* Get the specified MIME type(s) for the "Accept:" header.
* @return MIME type(s), or nullptr if not set.
*/
const TCHAR *IDownloader::requestedMimeType(void) const
{
return (!m_reqMimeType.empty()) ? m_reqMimeType.c_str() : nullptr;
}
/**
* Set the valid MIME type(s) for the "Accept:" header.
* @param mimeType Valid MIME type(s), or nullptr to clear.
*/
void IDownloader::setRequestedMimeType(const TCHAR *mimeType)
{
if (mimeType) {
m_reqMimeType = mimeType;
} else {
m_reqMimeType.clear();
}
}
/**
* Set the valid MIME type(s) for the "Accept:" header.
* @param mimeType Valid MIME type(s), or nullptr to clear.
*/
void IDownloader::setRequestedMimeType(const std::tstring &mimeType)
{
m_reqMimeType = mimeType;
}
/** Data accessors **/
/**

View File

@ -86,6 +86,24 @@ public:
*/
void setIfModifiedSince(time_t timestamp);
/**
* Get the specified MIME type(s) for the "Accept:" header.
* @return MIME type(s), or nullptr if not set.
*/
const TCHAR *requestedMimeType(void) const;
/**
* Set the valid MIME type(s) for the "Accept:" header.
* @param mimeType Valid MIME type(s), or nullptr to clear.
*/
void setRequestedMimeType(const TCHAR *mimeType);
/**
* Set the valid MIME type(s) for the "Accept:" header.
* @param mimeType Valid MIME type(s), or nullptr to clear.
*/
void setRequestedMimeType(const std::tstring &mimeType);
public:
/** Data accessors **/
@ -140,6 +158,7 @@ protected:
time_t m_mtime; // Last-Modified response
time_t m_if_modified_since; // If-Modified-Since request
std::tstring m_reqMimeType; // MIME type for "Accept:" header
size_t m_maxSize; // Maximum buffer size. (0 == unlimited)
std::tstring m_userAgent; // User-Agent

View File

@ -77,7 +77,8 @@ int WinInetDownloader::download(void)
}
}
tstring headers;
// Custom headers
tstring req_headers;
if (m_if_modified_since >= 0) {
// Add an "If-Modified-Since" header.
// FIXME: +4 is needed to avoid ERROR_INSUFFICIENT_BUFFER.
@ -87,17 +88,26 @@ int WinInetDownloader::download(void)
UnixTimeToSystemTime(m_if_modified_since, &st);
BOOL bRet = InternetTimeFromSystemTime(&st, INTERNET_RFC1123_FORMAT, szTime, sizeof(szTime));
if (bRet) {
headers = _T("If-Modified-Since: ");
headers += szTime;
req_headers = _T("If-Modified-Since: ");
req_headers += szTime;
}
}
if (!m_reqMimeType.empty()) {
// Add the "Accept:" header.
if (!req_headers.empty()) {
req_headers += _T("\r\n");
}
req_headers += _T("Accept: ");
req_headers += m_reqMimeType;
}
// Request the URL.
HINTERNET hURL = InternetOpenUrl(
hConnection, // hInternet
m_url.c_str(), // lpszUrl (Latin-1 characters only!)
!headers.empty() ? headers.data() : nullptr, // lpszHeaders
static_cast<DWORD>(headers.size()), // dwHeaderLength
!req_headers.empty() ? req_headers.data() : nullptr, // lpszHeaders
static_cast<DWORD>(req_headers.size()), // dwHeaderLength
dwFlags, // dwFlags
reinterpret_cast<DWORD_PTR>(this)); // dwContext
if (!hURL) {

View File

@ -213,6 +213,33 @@ static int get_file_size_and_mtime(const TCHAR *filename, off64_t *pFileSize, ti
return 0;
}
/**
* Get the MIME type for the specified cache key (or filename).
* @param cache_key Cache key (or filename)
* @return MIME type, or nullptr if not supported
*/
static const TCHAR *getMimeType(const TCHAR *cache_key)
{
// Find the last dot.
const TCHAR *const dotpos = _tcsrchr(cache_key, _T('.'));
if (!dotpos) {
return nullptr;
}
// Check the file extension.
const TCHAR *mimeType = nullptr;
if (!_tcscmp(dotpos, _T(".png"))) {
mimeType = _T("image/png");
} else if (!_tcscmp(dotpos, _T(".jpg"))) {
mimeType = _T("image/jpg");
} else if (!_tcscmp(dotpos, _T(".txt"))) {
mimeType = _T("text/plain");
}
return mimeType;
}
/**
* rp-download: Download an image from a supported online database.
* @param cache_key Cache key, e.g. "ds/cover/US/ADAE.png"
@ -519,6 +546,12 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
downloader.setIfModifiedSince(filemtime);
}
// Set the MIME type, if available.
const TCHAR *mimeType = getMimeType(cache_key);
if (mimeType) {
downloader.setRequestedMimeType(mimeType);
}
downloader.setUrl(full_url);
ret = downloader.download();
if (ret != 0) {