Skip to content

Commit 6043224

Browse files
committed
/vsicurl/: add a VSICURL_QUERY_STRING path specific option
This can for example be used when managing Shared Access Signatures (SAS) on application side, and not wanting to include the signature as part of the filename propagated through GDAL.
1 parent acdb4bd commit 6043224

File tree

5 files changed

+87
-9
lines changed

5 files changed

+87
-9
lines changed

autotest/gcore/vsicurl.py

+36
Original file line numberDiff line numberDiff line change
@@ -1573,3 +1573,39 @@ def test_vsicurl_cache_control_no_cache(server):
15731573
data = gdal.VSIFReadL(1, 6, f).decode("ascii")
15741574
gdal.VSIFCloseL(f)
15751575
assert data == "barbaz"
1576+
1577+
1578+
###############################################################################
1579+
# Test VSICURL_QUERY_STRING path specific option.
1580+
1581+
1582+
@gdaltest.enable_exceptions()
1583+
@pytest.mark.parametrize(
1584+
"filename,query_string",
1585+
[
1586+
("test_vsicurl_VSICURL_QUERY_STRING.bin", "foo=bar"),
1587+
("test_vsicurl_VSICURL_QUERY_STRING.bin?", "foo=bar"),
1588+
("test_vsicurl_VSICURL_QUERY_STRING.bin", "?foo=bar"),
1589+
("test_vsicurl_VSICURL_QUERY_STRING.bin?", "?foo=bar"),
1590+
],
1591+
)
1592+
def test_vsicurl_VSICURL_QUERY_STRING(server, filename, query_string):
1593+
1594+
gdal.VSICurlClearCache()
1595+
1596+
handler = webserver.SequentialHandler()
1597+
handler.add(
1598+
"HEAD",
1599+
"/test_vsicurl_VSICURL_QUERY_STRING.bin?foo=bar",
1600+
200,
1601+
{"Content-Length": "3"},
1602+
)
1603+
1604+
with webserver.install_http_handler(handler):
1605+
full_filename = f"/vsicurl/http://localhost:{server.port}/{filename}"
1606+
gdal.SetPathSpecificOption(full_filename, "VSICURL_QUERY_STRING", query_string)
1607+
try:
1608+
statres = gdal.VSIStatL(full_filename)
1609+
assert statres.size == 3
1610+
finally:
1611+
gdal.SetPathSpecificOption(full_filename, "VSICURL_QUERY_STRING", None)

doc/source/user/virtual_file_systems.rst

+6-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ Starting with GDAL 2.3, options can be passed in the filename with the following
382382
- retry_delay=number_in_seconds: default to 30. Setting this option overrides the behavior of the :config:`GDAL_HTTP_RETRY_DELAY` configuration option.
383383
- retry_codes=``ALL`` or comma-separated list of HTTP error codes. Setting this option overrides the behavior of the :config:`GDAL_HTTP_RETRY_CODES` configuration option. (GDAL >= 3.10)
384384
- list_dir=yes/no: whether an attempt to read the file list of the directory where the file is located should be done. Default to YES.
385-
- empty_dir=yes/no: whether to disable directory listing and disable logic in drivers to probe for individual side-car files. Default to NO.
385+
- empty_dir=yes/no: whether to disable directory listing and disable logic in drivers to probe for individual side-car files. Default to NO.
386386
- useragent=value: HTTP UserAgent header
387387
- referer=value: HTTP Referer header
388388
- cookie=value: HTTP Cookie header
@@ -419,6 +419,11 @@ forwarded when redirections are followed.
419419
That behavior can be configured by setting the
420420
:config:`CPL_VSIL_CURL_AUTHORIZATION_HEADER_ALLOWED_IF_REDIRECT` configuration option.
421421

422+
Starting with GDAL 3.11, a query string can be appended to a given /vsicurl/ filename by taking its value from the
423+
``VSICURL_QUERY_STRING`` path-specific option set with :cpp:func:`VSISetPathSpecificOption`.
424+
This can for example be used when managing Shared Access Signatures (SAS) on application side, and not
425+
wanting to include the signature as part of the filename propagated through GDAL.
426+
422427
Starting with GDAL 2.3, the :config:`GDAL_HTTP_MAX_RETRY` (number of attempts) and :config:`GDAL_HTTP_RETRY_DELAY` (in seconds) configuration option can be set, so that request retries are done in case of HTTP errors 429, 502, 503 or 504.
423428

424429
Starting with GDAL 3.6, the following configuration options control the TCP keep-alive functionality (cf https://daniel.haxx.se/blog/2020/02/10/curl-ootw-keepalive-time/ for a detailed explanation):

port/cpl_known_config_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,7 @@ constexpr static const char* const apszKnownConfigOptions[] =
10311031
"VSICURL_PC_SAS_SIGN_HREF_URL", // from cpl_vsil_curl.cpp
10321032
"VSICURL_PC_SAS_TOKEN_URL", // from cpl_vsil_curl.cpp
10331033
"VSICURL_PC_URL_SIGNING", // from cpl_vsil_curl.cpp
1034+
"VSICURL_QUERY_STRING", // from cpl_vsil_curl.cpp
10341035
"VSIS3_COPYFILE_USE_STREAMING_SOURCE", // from cpl_vsil_s3.cpp
10351036
"VSIS3_SIMULATE_THREADING", // from cpl_vsil_s3.cpp
10361037
"VSIS3_SYNC_MULTITHREADING", // from cpl_vsil_s3.cpp

port/cpl_vsil_curl.cpp

+42-8
Original file line numberDiff line numberDiff line change
@@ -948,9 +948,6 @@ namespace cpl
948948

949949
void VSICurlHandle::ManagePlanetaryComputerSigning() const
950950
{
951-
if (!m_bPlanetaryComputerURLSigning)
952-
return;
953-
954951
// Take global lock
955952
static std::mutex goMutex;
956953
std::lock_guard<std::mutex> oLock(goMutex);
@@ -1066,6 +1063,43 @@ void VSICurlHandle::ManagePlanetaryComputerSigning() const
10661063
}
10671064
}
10681065

1066+
/************************************************************************/
1067+
/* UpdateQueryString() */
1068+
/************************************************************************/
1069+
1070+
void VSICurlHandle::UpdateQueryString() const
1071+
{
1072+
if (m_bPlanetaryComputerURLSigning)
1073+
{
1074+
ManagePlanetaryComputerSigning();
1075+
}
1076+
else
1077+
{
1078+
const char *pszQueryString = VSIGetPathSpecificOption(
1079+
m_osFilename.c_str(), "VSICURL_QUERY_STRING", nullptr);
1080+
if (pszQueryString)
1081+
{
1082+
if (m_osFilename.back() == '?')
1083+
{
1084+
if (pszQueryString[0] == '?')
1085+
m_osQueryString = pszQueryString + 1;
1086+
else
1087+
m_osQueryString = pszQueryString;
1088+
}
1089+
else
1090+
{
1091+
if (pszQueryString[0] == '?')
1092+
m_osQueryString = pszQueryString;
1093+
else
1094+
{
1095+
m_osQueryString = "?";
1096+
m_osQueryString.append(pszQueryString);
1097+
}
1098+
}
1099+
}
1100+
}
1101+
}
1102+
10691103
/************************************************************************/
10701104
/* GetFileSizeOrHeaders() */
10711105
/************************************************************************/
@@ -1084,7 +1118,7 @@ vsi_l_offset VSICurlHandle::GetFileSizeOrHeaders(bool bSetError,
10841118

10851119
CURLM *hCurlMultiHandle = poFS->GetCurlMultiHandleFor(m_pszURL);
10861120

1087-
ManagePlanetaryComputerSigning();
1121+
UpdateQueryString();
10881122

10891123
std::string osURL(m_pszURL + m_osQueryString);
10901124
bool bRetryWithGet = false;
@@ -1857,7 +1891,7 @@ std::string VSICurlHandle::DownloadRegion(const vsi_l_offset startOffset,
18571891
begin:
18581892
CURLM *hCurlMultiHandle = poFS->GetCurlMultiHandleFor(m_pszURL);
18591893

1860-
ManagePlanetaryComputerSigning();
1894+
UpdateQueryString();
18611895

18621896
bool bHasExpired = false;
18631897

@@ -2432,7 +2466,7 @@ int VSICurlHandle::ReadMultiRange(int const nRanges, void **const ppData,
24322466
panSizes);
24332467
}
24342468

2435-
ManagePlanetaryComputerSigning();
2469+
UpdateQueryString();
24362470

24372471
bool bHasExpired = false;
24382472

@@ -3098,7 +3132,7 @@ size_t VSICurlHandle::PRead(void *pBuffer, size_t nSize,
30983132
std::string osURL;
30993133
{
31003134
std::lock_guard<std::mutex> oLock(m_oMutex);
3101-
ManagePlanetaryComputerSigning();
3135+
UpdateQueryString();
31023136
bool bHasExpired;
31033137
osURL = GetRedirectURLIfValid(bHasExpired, aosHTTPOptions);
31043138
}
@@ -3263,7 +3297,7 @@ void VSICurlHandle::AdviseRead(int nRanges, const vsi_l_offset *panOffsets,
32633297
nMaxSize += panSizes[i];
32643298
}
32653299

3266-
ManagePlanetaryComputerSigning();
3300+
UpdateQueryString();
32673301

32683302
bool bHasExpired = false;
32693303
CPLStringList aosHTTPOptions(m_aosHTTPOptions);

port/cpl_vsil_curl_class.h

+2
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ class VSICurlHandle : public VSIVirtualHandle
406406
mutable std::string m_osPlanetaryComputerCollection{};
407407
void ManagePlanetaryComputerSigning() const;
408408

409+
void UpdateQueryString() const;
410+
409411
int ReadMultiRangeSingleGet(int nRanges, void **ppData,
410412
const vsi_l_offset *panOffsets,
411413
const size_t *panSizes);

0 commit comments

Comments
 (0)