diff --git a/src/MissingAttributeError.php b/src/MissingAttributeError.php new file mode 100644 index 00000000..625bf4c0 --- /dev/null +++ b/src/MissingAttributeError.php @@ -0,0 +1,11 @@ +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 diff --git a/test/RequestTest.php b/test/RequestTest.php index e821c387..df18da60 100644 --- a/test/RequestTest.php +++ b/test/RequestTest.php @@ -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; @@ -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'); + } }