Skip to content

Commit

Permalink
Merge 28bd71a into 3282179
Browse files Browse the repository at this point in the history
  • Loading branch information
kelunik committed Nov 1, 2019
2 parents 3282179 + 28bd71a commit d00f436
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 25 deletions.
2 changes: 0 additions & 2 deletions src/Connection/Http1Connection.php
Expand Up @@ -166,8 +166,6 @@ private function hasStreamFor(Request $request): bool
/** @inheritdoc */
private function request(Request $request, CancellationToken $cancellation): Promise
{
$request = clone $request;

return call(function () use ($request, $cancellation) {
++$this->requestCounter;

Expand Down
2 changes: 0 additions & 2 deletions src/Connection/Http2Connection.php
Expand Up @@ -290,8 +290,6 @@ public function getTlsInfo(): ?TlsInfo

private function request(Request $request, CancellationToken $token): Promise
{
$request = clone $request;

// Remove defunct HTTP/1.x headers.
$request->removeHeader('host');
$request->removeHeader('connection');
Expand Down
2 changes: 1 addition & 1 deletion src/Connection/HttpStream.php
Expand Up @@ -46,7 +46,7 @@ public function request(Request $request, CancellationToken $token): Promise

$this->release = null;

return ($this->requestCallback)($request, $token);
return ($this->requestCallback)(clone $request, $token);
}

public function getLocalAddress(): SocketAddress
Expand Down
2 changes: 1 addition & 1 deletion src/Connection/InterceptedStream.php
Expand Up @@ -37,7 +37,7 @@ public function request(Request $request, CancellationToken $cancellation): Prom
$interceptor = $this->interceptor;
$this->interceptor = null;

return $interceptor->requestViaNetwork($request, $cancellation, $this->stream);
return $interceptor->requestViaNetwork(clone $request, $cancellation, $this->stream);
}

public function getLocalAddress(): SocketAddress
Expand Down
2 changes: 1 addition & 1 deletion src/Interceptor/RetryRequests.php
Expand Up @@ -28,7 +28,7 @@ public function request(Request $request, CancellationToken $cancellation, Deleg

do {
try {
return yield $next->request(clone $request, $cancellation);
return yield $next->request($request, $cancellation);
} catch (UnprocessedRequestException $exception) {
// Request was deemed retryable by connection, so carry on.
} catch (SocketException $exception) {
Expand Down
5 changes: 3 additions & 2 deletions src/PooledHttpClient.php
Expand Up @@ -44,9 +44,10 @@ public function __construct(?ConnectionPool $connectionPool = null)
public function request(Request $request, ?CancellationToken $cancellation = null): Promise
{
return call(function () use ($request, $cancellation) {
$request = clone $request;
$cancellation = $cancellation ?? new NullCancellationToken;

$stream = yield $this->connectionPool->getStream(clone $request, $cancellation);
$stream = yield $this->connectionPool->getStream($request, $cancellation);

\assert($stream instanceof Stream);

Expand All @@ -56,7 +57,7 @@ public function request(Request $request, ?CancellationToken $cancellation = nul
$stream = new InterceptedStream($stream, $interceptor);
}

return yield $stream->request(clone $request, $cancellation);
return yield $stream->request($request, $cancellation);
});
}

Expand Down
51 changes: 35 additions & 16 deletions src/Request.php
Expand Up @@ -18,6 +18,16 @@ final class Request extends Message
public const DEFAULT_HEADER_SIZE_LIMIT = 2 * 8192;
public const DEFAULT_BODY_SIZE_LIMIT = 10485760;

private static function clone($value)
{
if ($value === null || \is_scalar($value)) {
return $value;
}

// force deep cloning
return \unserialize(\serialize($value), ['allowed_classes' => true]);
}

/** @var string[] */
private $protocolVersions = ['1.1', '2'];

Expand Down Expand Up @@ -59,9 +69,9 @@ final class Request extends Message
*/
public function __construct($uri, string $method = "GET")
{
$this->uri = $uri instanceof UriInterface ? $uri : $this->createUriFromString($uri);
$this->method = $method;
$this->body = new StringBody("");
$this->setUri($uri);
$this->setMethod($method);
$this->setBody('');
}

/**
Expand Down Expand Up @@ -305,17 +315,20 @@ public function setBodySizeLimit(int $bodySizeLimit): void
}

/**
* @return mixed[] An array of all request attributes in the request's mutable local storage, indexed by name.
* Note: This method returns a deep clone of the request's attributes, so you can't modify the request attributes
* by modifying the returned value in any way.
*
* @return mixed[] An array of all request attributes in the request's local storage, indexed by name.
*/
public function getAttributes(): array
{
return $this->attributes;
return self::clone($this->attributes);
}

/**
* Check whether a variable with the given name exists in the request's mutable local storage.
* Check whether a variable with the given name exists in the request's local storage.
*
* Each request has its own mutable local storage to which applications and interceptors may read and write data.
* Each request has its own local storage to which applications and interceptors may read and write data.
* Other interceptors which are aware of this data can then access it without the server being tightly coupled to
* specific implementations.
*
Expand All @@ -329,12 +342,15 @@ public function hasAttribute(string $name): bool
}

/**
* Retrieve a variable from the request's mutable local storage.
* Retrieve a variable from the request's local storage.
*
* Each request has its own mutable local storage to which applications and interceptors may read and write data.
* Each request has its own local storage to which applications and interceptors may read and write data.
* Other interceptors which are aware of this data can then access it without the server being tightly coupled to
* specific implementations.
*
* Note: This method returns a deep clone of the request's attribute, so you can't modify the request attribute
* by modifying the returned value in any way.
*
* @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
*
* @return mixed
Expand All @@ -347,32 +363,35 @@ public function getAttribute(string $name)
throw new MissingAttributeError("The requested attribute '{$name}' does not exist");
}

return $this->attributes[$name];
return self::clone($this->attributes[$name]);
}

/**
* Assign a variable to the request's mutable local storage.
* Assign a variable to the request's local storage.
*
* Each request has its own mutable local storage to which applications and interceptors may read and write data.
* Each request has its own local storage to which applications and interceptors may read and write data.
* Other interceptors which are aware of this data can then access it without the server being tightly coupled to
* specific implementations.
*
* Note: This method performs a deep clone of the value via serialization, so you can't modify the given value
* after setting it.
*
* **Example**
*
* ```php
* $request->setAttribute(Timing::class, $stopWatch);
* ```
*
* @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
* @param mixed $value Value of the attribute, might be any value.
* @param mixed $value Value of the attribute, might be any serializable value.
*/
public function setAttribute(string $name, $value): void
{
$this->attributes[$name] = $value;
$this->attributes[$name] = self::clone($value);
}

/**
* Remove an attribute from the request's mutable local storage.
* Remove an attribute from the request's local storage.
*
* @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
*
Expand All @@ -388,7 +407,7 @@ public function removeAttribute(string $name): void
}

/**
* Remove all attributes from the request's mutable local storage.
* Remove all attributes from the request's local storage.
*/
public function removeAttributes(): void
{
Expand Down
11 changes: 11 additions & 0 deletions test/RequestTest.php
Expand Up @@ -126,4 +126,15 @@ public function testAttributes(): void

$request->getAttribute('foo');
}

public function testRemoveAttributes(): void
{
$request = new Request("http://127.0.0.1/");
$request->setAttribute('foo', 'bar');
$request->setAttribute('a', 'b');

$request->removeAttributes();

$this->assertSame([], $request->getAttributes());
}
}

0 comments on commit d00f436

Please sign in to comment.