Skip to content

Commit dc0fde8

Browse files
committed
feat(Storage): add support for idempotency token
1 parent 284f348 commit dc0fde8

5 files changed

Lines changed: 321 additions & 33 deletions

File tree

Storage/src/Connection/Rest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
/**
34
* Copyright 2015 Google Inc. All Rights Reserved.
45
*
@@ -19,7 +20,6 @@
1920

2021
use Google\Auth\GetUniverseDomainInterface;
2122
use Google\Cloud\Core\RequestBuilder;
22-
use Google\Cloud\Core\RequestWrapper;
2323
use Google\Cloud\Core\RestTrait;
2424
use Google\Cloud\Core\Retry;
2525
use Google\Cloud\Core\Upload\AbstractUploader;
@@ -141,7 +141,7 @@ public function __construct(array $config = [])
141141

142142
$this->apiEndpoint = $this->getApiEndpoint(null, $config, self::DEFAULT_API_ENDPOINT_TEMPLATE);
143143

144-
$this->setRequestWrapper(new RequestWrapper($config));
144+
$this->setRequestWrapper(new StorageRequestWrapper($config));
145145
$this->setRequestBuilder(new RequestBuilder(
146146
$config['serviceDefinitionPath'],
147147
$this->apiEndpoint
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2024 Google Inc. All Rights Reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace Google\Cloud\Storage\Connection;
20+
21+
use Google\Cloud\Core\RequestWrapper;
22+
use Psr\Http\Message\RequestInterface;
23+
use Ramsey\Uuid\Uuid;
24+
25+
/**
26+
* A wrapper for requests which adds an Idempotency Token.
27+
*
28+
* @internal
29+
*/
30+
class StorageRequestWrapper extends RequestWrapper
31+
{
32+
/**
33+
* @param RequestInterface $request A PSR-7 request.
34+
* @param array $options [optional]
35+
* @return mixed
36+
*/
37+
public function send(RequestInterface $request, array $options = [])
38+
{
39+
$options = $this->addToken($request, $options);
40+
return parent::send($request, $options);
41+
}
42+
43+
/**
44+
* @param RequestInterface $request A PSR-7 request.
45+
* @param array $options [optional]
46+
* @return mixed
47+
*/
48+
public function sendAsync(RequestInterface $request, array $options = [])
49+
{
50+
$options = $this->addToken($request, $options);
51+
return parent::sendAsync($request, $options);
52+
}
53+
54+
/**
55+
* Helper to inject the token.
56+
*
57+
* @param RequestInterface $request
58+
* @param array $options
59+
* @return array
60+
*/
61+
private function addToken(RequestInterface $request, array $options)
62+
{
63+
$method = strtoupper($request->getMethod());
64+
if ($method === 'GET' || $method === 'HEAD' || $method === 'OPTIONS') {
65+
return $options;
66+
}
67+
68+
$hasTokenInOptions = false;
69+
if (isset($options['restOptions']['headers'])) {
70+
foreach ($options['restOptions']['headers'] as $key => $value) {
71+
if (strtolower($key) === 'x-goog-gcs-idempotency-token') {
72+
$hasTokenInOptions = true;
73+
break;
74+
}
75+
}
76+
}
77+
78+
if (!$hasTokenInOptions && !$request->hasHeader('x-goog-gcs-idempotency-token')) {
79+
$token = Uuid::uuid4()->toString();
80+
if (isset($options['retryHeaders'])) {
81+
foreach ($options['retryHeaders'] as $header) {
82+
if (strpos($header, 'gccl-invocation-id/') === 0) {
83+
$extractedToken = substr($header, 19);
84+
if ($extractedToken !== false && $extractedToken !== '') {
85+
$token = $extractedToken;
86+
}
87+
break;
88+
}
89+
}
90+
}
91+
$options['restOptions']['headers']['x-goog-gcs-idempotency-token'] = $token;
92+
}
93+
return $options;
94+
}
95+
}

0 commit comments

Comments
 (0)