Skip to content

Commit

Permalink
Merge pull request #2 from mnapoli/fix-1
Browse files Browse the repository at this point in the history
Fix #1 Support for POST body
  • Loading branch information
mnapoli committed May 9, 2018
2 parents 1556b0e + 5d7d943 commit 58aa3da
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/tests/Bridge/Symfony/cache
/tests/Bridge/Symfony/logs
/.bref/
/.php_cs.cache
29 changes: 29 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
language: php

notifications:
email:
on_success: never

php:
- 7.1
- 7.2
- nightly

matrix:
fast_finish: true
allow_failures:
- php: nightly
include:
- php: 7.1
env: dependencies=lowest

cache:
directories:
- $HOME/.composer/cache

before_script:
- composer install -n
- if [ "$dependencies" = "lowest" ]; then composer update --prefer-lowest --prefer-stable -n; fi;

script:
- vendor/bin/phpunit
2 changes: 1 addition & 1 deletion src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public function run() : void
// Run the appropriate handler
if (isset($event['httpMethod'])) {
// HTTP request
$request = (new RequestFactory)->fromLambdaEvent($event);
$request = RequestFactory::fromLambdaEvent($event);
$response = $this->httpHandler->handle($request);
$output = LambdaResponse::fromPsr7Response($response)->toJson();
} elseif (isset($event['cli'])) {
Expand Down
31 changes: 26 additions & 5 deletions src/Bridge/Psr7/RequestFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,39 @@
namespace Bref\Bridge\Psr7;

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;
use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\Stream;

/**
* Create a PSR-7 request from a lambda event.
* Creates PSR-7 requests.
*
* @author Matthieu Napoli <matthieu@mnapoli.fr>
*/
class RequestFactory
{
public function fromLambdaEvent(array $event) : ServerRequestInterface
/**
* Create a PSR-7 server request from an AWS Lambda HTTP event.
*/
public static function fromLambdaEvent(array $event) : ServerRequestInterface
{
$method = $event['httpMethod'] ?? 'GET';
$query = $event['queryStringParameters'] ?? [];
parse_str($event['body'] ?? '', $request);
$bodyString = $event['body'] ?? '';
$body = self::createBodyStream($bodyString);
$parsedBody = null;
$files = [];
$uri = $event['requestContext']['path'] ?? '/';
$headers = $event['headers'] ?? [];
$protocolVersion = $event['requestContext']['protocol'] ?? '1.1';
// TODO
$cookies = [];

$contentType = $headers['Content-Type'] ?? null;
if ($method === 'POST' && $contentType === 'application/x-www-form-urlencoded') {
parse_str($bodyString, $parsedBody);
}

$server = [
'SERVER_PROTOCOL' => $protocolVersion,
'REQUEST_METHOD' => $method,
Expand All @@ -39,12 +51,21 @@ public function fromLambdaEvent(array $event) : ServerRequestInterface
$files,
$uri,
$method,
'file:///dev/null',
$body,
$headers,
$cookies,
$query,
$request,
$parsedBody,
$protocolVersion
);
}

private static function createBodyStream(string $body) : StreamInterface
{
$stream = fopen('php://memory', 'r+');
fwrite($stream, $body);
rewind($stream);

return new Stream($stream);
}
}
109 changes: 109 additions & 0 deletions tests/Bridge/Psr7/RequestFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php
declare(strict_types=1);

namespace Bref\Test\Bridge\Psr7;

use Bref\Bridge\Psr7\RequestFactory;
use PHPUnit\Framework\TestCase;

class RequestFactoryTest extends TestCase
{
public function test create basic request()
{
$currentTimestamp = time();

$request = RequestFactory::fromLambdaEvent([
'httpMethod' => 'GET',
'queryStringParameters' => [
'foo' => 'bar',
'bim' => 'baz',
],
'requestContext' => [
'protocol' => '1.1',
'path' => '/test',
'requestTimeEpoch' => $currentTimestamp,
],
'headers' => [
],
]);

self::assertEquals('GET', $request->getMethod());
self::assertEquals(['foo' => 'bar', 'bim' => 'baz'], $request->getQueryParams());
self::assertEquals('1.1', $request->getProtocolVersion());
self::assertEquals('/test', $request->getUri()->__toString());
self::assertEquals('', $request->getBody()->getContents());
self::assertEquals([], $request->getAttributes());
$serverParams = $request->getServerParams();
unset($serverParams['DOCUMENT_ROOT']);
self::assertEquals([
'SERVER_PROTOCOL' => '1.1',
'REQUEST_METHOD' => 'GET',
'REQUEST_TIME' => $currentTimestamp,
'QUERY_STRING' => 'foo=bar&bim=baz',
'REQUEST_URI' => '/test',
], $serverParams);
self::assertEquals('/test', $request->getRequestTarget());
self::assertEquals([], $request->getHeaders());
}

public function test non empty body()
{
$request = RequestFactory::fromLambdaEvent([
'httpMethod' => 'GET',
'body' => 'test test test',
]);

self::assertEquals('test test test', $request->getBody()->getContents());
}

public function test POST body is parsed()
{
$request = RequestFactory::fromLambdaEvent([
'httpMethod' => 'POST',
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'body' => 'foo=bar&bim=baz',
]);
self::assertEquals('POST', $request->getMethod());
self::assertEquals(['foo' => 'bar', 'bim' => 'baz'], $request->getParsedBody());
}

public function test POST JSON body is not parsed()
{
$request = RequestFactory::fromLambdaEvent([
'httpMethod' => 'POST',
'headers' => [
'Content-Type' => 'application/json',
],
'body' => json_encode(['foo' => 'bar']),
]);
self::assertEquals('POST', $request->getMethod());
self::assertEquals(null, $request->getParsedBody());
self::assertEquals(['foo' => 'bar'], json_decode($request->getBody()->getContents(), true));
}

public function test multipart form data is not supported()
{
$request = RequestFactory::fromLambdaEvent([
'httpMethod' => 'POST',
'headers' => [
'Content-Type' => 'multipart/form-data',
],
'body' => 'abcd',
]);
self::assertEquals('POST', $request->getMethod());
self::assertNull(null, $request->getParsedBody());
}

public function test cookies are not supported()
{
$request = RequestFactory::fromLambdaEvent([
'httpMethod' => 'GET',
'headers' => [
'Cookie' => 'theme=light',
],
]);
self::assertEquals([], $request->getCookieParams());
}
}

0 comments on commit 58aa3da

Please sign in to comment.