Skip to content

Commit

Permalink
truncate the body to the specified length
Browse files Browse the repository at this point in the history
  • Loading branch information
Baptouuuu committed Feb 12, 2023
1 parent 56bde91 commit 573ba7e
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
9 changes: 9 additions & 0 deletions fixtures/unbounded-post.txt
@@ -0,0 +1,9 @@
POST /some-form HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: innmind.com
Content-Type: application/x-www-form-urlencoded
Accept-Language: fr-fr
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

some[key]=value&foo=bar
33 changes: 31 additions & 2 deletions src/Request/Buffer/Body.php
Expand Up @@ -8,6 +8,7 @@
Message\Method,
ProtocolVersion,
Headers,
Header\ContentLength,
};
use Innmind\Filesystem\File\Content;
use Innmind\Url\Url;
Expand All @@ -22,19 +23,26 @@ final class Body implements State
private Url $url;
private ProtocolVersion $protocol;
private Headers $headers;
/** @var Maybe<0|positive-int> */
private Maybe $length;
private Str $body;

/**
* @param Maybe<0|positive-int> $length
*/
private function __construct(
Method $method,
Url $url,
ProtocolVersion $protocol,
Headers $headers,
Maybe $length,
Str $body,
) {
$this->method = $method;
$this->url = $url;
$this->protocol = $protocol;
$this->headers = $headers;
$this->length = $length;
$this->body = $body;
}

Expand All @@ -44,17 +52,38 @@ public static function new(
ProtocolVersion $protocol,
Headers $headers,
): self {
return new self($method, $url, $protocol, $headers, Str::of(''));
/** @var Maybe<0|positive-int> */
$length = $headers
->find(ContentLength::class)
->flatMap(static fn($header) => $header->values()->find(static fn() => true)) // first
->map(static fn($length) => (int) $length->toString()) // at this moment the header doesn't expose directly the int
->filter(static fn($length) => $length >= 0);

return new self(
$method,
$url,
$protocol,
$headers,
$length,
Str::of(''),
);
}

public function add(Str $chunk): self
{
$body = $this->body->append($chunk->toString());
$body = $this->length->match(
static fn($length) => $body->take($length),
static fn() => $body,
);

return new self(
$this->method,
$this->url,
$this->protocol,
$this->headers,
$this->body->append($chunk->toString()),
$this->length,
$body,
);
}

Expand Down
67 changes: 67 additions & 0 deletions tests/Request/ParseTest.php
Expand Up @@ -144,6 +144,73 @@ public function testParsePost()
static fn() => null,
),
);
$this->assertSame(
'some[key]=value&foo=bar',
$request->body()->toString(),
);
});
}

public function testParseUnboundedPost()
{
$this
->forAll(Set\Integers::above(1))
->then(function($size) {
$chunks = Str::of(\file_get_contents('fixtures/unbounded-post.txt'))->chunk($size);
$parse = new Parse(new Clock);

$request = $parse($chunks)->match(
static fn($request) => $request,
static fn() => null,
);

$this->assertInstanceOf(Request::class, $request);
$this->assertSame(Method::post, $request->method());
$this->assertSame('/some-form', $request->url()->toString());
$this->assertSame(ProtocolVersion::v11, $request->protocolVersion());
$this->assertCount(6, $request->headers());
$this->assertSame(
'User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)',
$request->headers()->get('user-agent')->match(
static fn($header) => $header->toString(),
static fn() => null,
),
);
$this->assertSame(
'Host: innmind.com',
$request->headers()->get('host')->match(
static fn($header) => $header->toString(),
static fn() => null,
),
);
$this->assertSame(
'Content-Type: application/x-www-form-urlencoded',
$request->headers()->get('content-type')->match(
static fn($header) => $header->toString(),
static fn() => null,
),
);
$this->assertSame(
'Accept-Language: fr-fr;q=1',
$request->headers()->get('accept-language')->match(
static fn($header) => $header->toString(),
static fn() => null,
),
);
$this->assertSame(
'Accept-Encoding: gzip;q=1, deflate;q=1',
$request->headers()->get('accept-encoding')->match(
static fn($header) => $header->toString(),
static fn() => null,
),
);
$this->assertSame(
'Connection: Keep-Alive',
$request->headers()->get('connection')->match(
static fn($header) => $header->toString(),
static fn() => null,
),
);
$this->assertSame(
"some[key]=value&foo=bar\n",
$request->body()->toString(),
Expand Down

0 comments on commit 573ba7e

Please sign in to comment.