Skip to content

Commit

Permalink
Add support for request attributes
Browse files Browse the repository at this point in the history
Fixes #205.
  • Loading branch information
kelunik committed Oct 8, 2019
1 parent 46442bc commit cf66797
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/MissingAttributeError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Amp\Http\Client;

final class MissingAttributeError extends \Error
{
public function __construct(string $message)
{
parent::__construct($message);
}
}
86 changes: 86 additions & 0 deletions src/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ final class Request extends Message
/** @var callable|null */
private $onPush;

/** @var mixed[] */
private $attributes = [];

/**
* Request constructor.
*
Expand Down Expand Up @@ -298,6 +301,89 @@ public function setBodySizeLimit(int $bodySizeLimit): void
$this->bodySizeLimit = $bodySizeLimit;
}

/**
* @return mixed[] An array of all request attributes in the request's mutable local storage, indexed by name.
*/
public function getAttributes(): array
{
return $this->attributes;
}

/**
* Check whether a variable with the given name exists in the request's mutable local storage.
*
* Each request has its own mutable 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.
*
* @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
*
* @return bool
*/
public function hasAttribute(string $name): bool
{
return \array_key_exists($name, $this->attributes);
}

/**
* Retrieve a variable from the request's mutable local storage.
*
* Each request has its own mutable 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.
*
* @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
*
* @return mixed
*
* @throws MissingAttributeError If an attribute with the given name does not exist.
*/
public function getAttribute(string $name)
{
if (!$this->hasAttribute($name)) {
throw new MissingAttributeError("The requested attribute '{$name}' does not exist");
}

return $this->attributes[$name];
}

/**
* Assign a variable to the request's mutable local storage.
*
* Each request has its own mutable 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.
*
* **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.
*/
public function setAttribute(string $name, $value): void
{
$this->attributes[$name] = $value;
}

/**
* Remove an attribute from the request's mutable local storage.
*
* @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
*
* @throws MissingAttributeError If an attribute with the given name does not exist.
*/
public function removeAttribute(string $name): void
{
if (!$this->hasAttribute($name)) {
throw new MissingAttributeError("The requested attribute '{$name}' does not exist");
}

unset($this->attributes[$name]);
}

public function isIdempotent(): bool
{
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
Expand Down
19 changes: 19 additions & 0 deletions test/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Amp\Http\Client\Test;

use Amp\Http\Client\Body\StringBody;
use Amp\Http\Client\MissingAttributeError;
use Amp\Http\Client\Request;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -109,4 +110,22 @@ public function testBody(): void
$this->expectException(\TypeError::class);
$request->setBody(new \stdClass);
}

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

$this->assertSame('bar', $request->getAttribute('foo'));
$this->assertTrue($request->hasAttribute('foo'));
$this->assertSame(['foo' => 'bar'], $request->getAttributes());

$request->removeAttribute('foo');

$this->assertFalse($request->hasAttribute('foo'));

$this->expectException(MissingAttributeError::class);

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

0 comments on commit cf66797

Please sign in to comment.