Storage v1.51.0: uploads bypass client-level restOptions (proxy, verify) due to per-call override
@Hectorhammett is already working on this.
Since May 26, 2026.
Assessment
This issue has not been assessed yet.
Description
Environment
google/cloud-storage:v1.51.0google/cloud-core:v1.72.0- PHP: 8.x
Summary
Since google/cloud-storage v1.51.0, uploads via Bucket::upload() (and the underlying MultipartUploader / ResumableUploader) no longer honor the restOptions passed to the StorageClient constructor — notably proxy and verify. The change is a regression introduced by #8825 ("Enable full object checksum validation on JSON path").
For environments where outbound HTTPS to storage.googleapis.com is only reachable through an HTTP forward proxy, this breaks all uploads after upgrading from v1.50.x.
Reproduction
use Google\Cloud\Storage\StorageClient;
$storage = new StorageClient([
'restOptions' => [
'proxy' => 'http://proxy.example.com:8080',
'verify' => false,
],
// ... credentials etc.
]);
$bucket = $storage->bucket('my-bucket');
$bucket->upload(fopen('/tmp/some.csv', 'r'), ['name' => 'foo.csv']);
- v1.49.x / v1.50.x: the upload request is sent through
http://proxy.example.com:8080. - v1.51.0: the upload request goes direct, ignoring the proxy and failing in proxy-only environments.
Metadata calls (e.g. $bucket->info(), $bucket->exists()) and auth token fetches still go through the proxy as expected. Only the actual upload POST is affected.
Root cause
#8825 added X-Goog-Hash header injection in Storage/src/Connection/Rest.php::resolveUploadOptions():
if (!empty($xGoogHashHeader)) {
$args['uploaderOptions']['restOptions']['headers']['X-Goog-Hash'] = $xGoogHashHeader;
}
uploaderOptions is then passed to MultipartUploader / ResumableUploader, stored as $this->requestOptions, and forwarded to RequestWrapper::send($request, $this->requestOptions).
In Core/src/RequestWrapper.php::getRequestOptions():
$restOptions = $options['restOptions'] ?? $this->restOptions;
Per-call $options['restOptions'] replaces the wrapper's stored $this->restOptions instead of merging with it. Before v1.51.0 the uploader didn't pass per-call restOptions (no header injection), so the stored restOptions — including proxy and verify — was used. Now that the uploader always sets restOptions.headers.X-Goog-Hash (because chooseValidationMethod() defaults to crc32 / md5), the stored restOptions is silently dropped on every upload.
Suggested fixes
Either:
- In
RequestWrapper::getRequestOptions()— merge per-callrestOptionswith the stored one rather than overriding (deep merge, with per-call values winning on conflict). This is the more general fix and preserves the existing API contract for callers that only want to add headers. - In
Rest::resolveUploadOptions()— instead of writing to$args['uploaderOptions']['restOptions']['headers']['X-Goog-Hash'], pass the header through a dedicatedheadersfield that gets merged with the wrapper's existingrestOptionsat send time.
(1) is preferable since it also covers the same pattern in #9210 (downloads CRC32C validation) before it lands.
Note
The bug appears to extend to #9210 (object download checksum validation, currently open) which uses the same uploaderOptions.restOptions.headers pattern — worth fixing before that PR merges.
- Dominant language
- PHP
- Stars
- 1.2k
- Forks
- 464
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 103
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from googleapis/google-cloud-php
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
googleapis/google-cloud-php#9730 ·
-
type: feature request
Difficulty 1/5 Under an hour Newbie friendliness 75/100
googleapis/google-cloud-php#9716 · 11 reactions ·
-
Difficulty 3/5 1-2 days Newbie friendliness 65/100
googleapis/google-cloud-php#9725 ·
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
googleapis/google-cloud-php#9675 · 1 comment ·
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
googleapis/google-cloud-php#9674 · 1 comment ·
All issues in googleapis/google-cloud-php
Similar issues
-
tooling
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
UX
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
ProfessionalWiki/NeoWiki#1525 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
OpenConext/OpenConext-engineblock#2122 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Automattic/safe-publish#594 ·