From 62bf98360576168f98b00f3bdcf6182b5ed661f5 Mon Sep 17 00:00:00 2001 From: Niklas Keller Date: Tue, 22 Aug 2023 21:45:54 +0200 Subject: [PATCH] Remove attribute dependency from FormParser (#14) Instead of parseRequest, we provide Form::fromRequest now. --- README.md | 4 ++-- examples/basic-form.php | 4 ++-- src/Form.php | 26 ++++++++++++++++++++++++++ src/FormParser.php | 10 +--------- src/functions.php | 16 ---------------- test/FormTest.php | 7 +++---- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 8eb5684..ca2792f 100644 --- a/README.md +++ b/README.md @@ -17,14 +17,14 @@ Basic usage works by calling `parseForm($request)`, which will buffer the reques ```php "text/plain; charset=utf-8" diff --git a/examples/basic-form.php b/examples/basic-form.php index f978e70..eac0ff4 100644 --- a/examples/basic-form.php +++ b/examples/basic-form.php @@ -6,7 +6,7 @@ use Amp\ByteStream; use Amp\Http\HttpStatus; use Amp\Http\Server\DefaultErrorHandler; -use Amp\Http\Server\FormParser; +use Amp\Http\Server\FormParser\Form; use Amp\Http\Server\Request; use Amp\Http\Server\RequestHandler\ClosureRequestHandler; use Amp\Http\Server\Response; @@ -50,7 +50,7 @@ ); } - $form = FormParser\parseForm($request); + $form = Form::fromRequest($request); $html = << diff --git a/src/Form.php b/src/Form.php index 2e7651d..54a2568 100644 --- a/src/Form.php +++ b/src/Form.php @@ -4,12 +4,38 @@ use Amp\ForbidCloning; use Amp\ForbidSerialization; +use Amp\Http\Server\Request; final class Form { use ForbidCloning; use ForbidSerialization; + private static FormParser $formParser; + + /** + * Try parsing the request's body with either application/x-www-form-urlencoded or multipart/form-data. + */ + public static function fromRequest(Request $request, ?FormParser $formParser = null): self + { + if ($request->hasAttribute(Form::class)) { + return $request->getAttribute(Form::class); + } + + $form = ($formParser ?? self::getFormParser())->parseForm($request); + + $request->setAttribute(Form::class, $form); + + return $form; + } + + private static function getFormParser(): FormParser + { + self::$formParser ??= new FormParser(); + + return self::$formParser; + } + /** @var list|null */ private ?array $names = null; diff --git a/src/FormParser.php b/src/FormParser.php index be95683..8b97167 100644 --- a/src/FormParser.php +++ b/src/FormParser.php @@ -37,10 +37,6 @@ public function __construct(?int $fieldCountLimit = null) */ public function parseForm(Request $request): Form { - if ($request->hasAttribute(Form::class)) { - return $request->getAttribute(Form::class); - } - $boundary = parseContentBoundary($request->getHeader('content-type') ?? ''); // Don't consume body if we don't have a form content type @@ -50,11 +46,7 @@ public function parseForm(Request $request): Form throw new HttpErrorException(HttpStatus::BAD_REQUEST, "Request body ended unexpectedly"); } - $form = $this->parseBody($body, $boundary); - - $request->setAttribute(Form::class, $form); - - return $form; + return $this->parseBody($body, $boundary); } /** diff --git a/src/functions.php b/src/functions.php index 62aa84f..2f56155 100644 --- a/src/functions.php +++ b/src/functions.php @@ -2,22 +2,6 @@ namespace Amp\Http\Server\FormParser; -use Amp\Http\Server\HttpErrorException; -use Amp\Http\Server\Request; - -/** - * Try parsing the request's body with either application/x-www-form-urlencoded or multipart/form-data. - * - * @throws HttpErrorException - */ -function parseForm(Request $request): Form -{ - static $parser; - $parser ??= new FormParser(); - - return $parser->parseForm($request); -} - /** * Parse the given content-type and returns the boundary if parsing is supported, * an empty string content-type is url-encoded mode or null if not supported. diff --git a/test/FormTest.php b/test/FormTest.php index 80ba18f..7712b5f 100644 --- a/test/FormTest.php +++ b/test/FormTest.php @@ -10,7 +10,6 @@ use Amp\Http\Server\Response; use Amp\PHPUnit\AsyncTestCase; use League\Uri\Http; -use function Amp\Http\Server\FormParser\parseForm; class FormTest extends AsyncTestCase { @@ -55,7 +54,7 @@ public function testWwwFormUrlencoded(): void $handler = new ClosureRequestHandler(function (Request $request) use ($callback): Response { $callback(); - $form = parseForm($request); + $form = Form::fromRequest($request); $this->assertSame('bar', $form->getValue('foo')); $this->assertSame('y', $form->getValue('x')); @@ -73,7 +72,7 @@ public function testWwwFormUrlencoded(): void public function testNonForm(): void { $handler = new ClosureRequestHandler(function (Request $request): Response { - parseForm($request); + Form::fromRequest($request); $this->assertTrue($request->hasAttribute(Form::class)); // attribute is set either way $this->assertSame('{}', $request->getBody()->buffer()); @@ -93,7 +92,7 @@ public function testNone(): void $handler = new ClosureRequestHandler(function (Request $request): Response { $this->assertFalse($request->hasAttribute(Form::class)); - $form = parseForm($request); + $form = Form::fromRequest($request); self::assertSame([], $form->getNames()); $this->assertTrue($request->hasAttribute(Form::class)); // attribute is set either way