Skip to content

Commit

Permalink
Create an interface (#5)
Browse files Browse the repository at this point in the history
* Create an interface

* cs

* Added getHeadersFromServer

* cs

* Added tests

* cs

* Added changelog

* Allow to set body

* cs
  • Loading branch information
Nyholm committed Jul 30, 2018
1 parent 2fd031e commit a9e7240
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 22 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,6 +2,19 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 0.1.0 - Unreleased
## 0.1.2

### Added

- `ServerRequestCreatorInterface`
- `ServerRequestCreator::getHeadersFromServer`

## 0.1.1

### Added

Better testing

## 0.1.0

First release
75 changes: 57 additions & 18 deletions src/ServerRequestCreator.php
Expand Up @@ -8,11 +8,12 @@
use Interop\Http\Factory\UploadedFileFactoryInterface;
use Interop\Http\Factory\UriFactoryInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UploadedFileInterface;
use Interop\Http\Factory\ServerRequestFactoryInterface;
use Psr\Http\Message\UriInterface;

class ServerRequestCreator
class ServerRequestCreator implements ServerRequestCreatorInterface
{
private $serverRequestFactory;

Expand All @@ -35,11 +36,7 @@ public function __construct(
}

/**
* Create a new server request from the current environment variables.
* Defaults to a GET request to minimise the risk of an \InvalidArgumentException.
* Includes the current request headers as supplied by the server through `getallheaders()`.
*
* @throws \InvalidArgumentException If no valid method or URI can be determined.
* {@inheritdoc}
*/
public function fromGlobals(): ServerRequestInterface
{
Expand All @@ -53,18 +50,9 @@ public function fromGlobals(): ServerRequestInterface
}

/**
* Create a new server request from a set of arrays.
*
* @param array $server Typically $_SERVER or similar structure.
* @param array $headers Typically the output of getallheaders() or similar structure.
* @param array $cookie Typically $_COOKIE or similar structure.
* @param array $get Typically $_GET or similar structure.
* @param array $post Typically $_POST or similar structure.
* @param array $files Typically $_FILES or similar structure.
*
* @throws \InvalidArgumentException If no valid method or URI can be determined.
* {@inheritdoc}
*/
public function fromArrays(array $server, array $headers = [], array $cookie = [], array $get = [], array $post = [], array $files = []): ServerRequestInterface
public function fromArrays(array $server, array $headers = [], array $cookie = [], array $get = [], array $post = [], array $files = [], $body = null): ServerRequestInterface
{
$method = $this->getMethodFromEnv($server);
$uri = $this->getUriFromEnvWithHTTP($server);
Expand All @@ -75,12 +63,63 @@ public function fromArrays(array $server, array $headers = [], array $cookie = [
$serverRequest = $serverRequest->withAddedHeader($name, $value);
}

return $serverRequest
$serverRequest = $serverRequest
->withProtocolVersion($protocol)
->withCookieParams($cookie)
->withQueryParams($get)
->withParsedBody($post)
->withUploadedFiles($this->normalizeFiles($files));

if (null === $body) {
return $serverRequest;
}

if (is_resource($body)) {
$body = $this->streamFactory->createStreamFromResource($body);
} elseif (is_string($body)) {
$body = $this->streamFactory->createStream($body);
} elseif (!$body instanceof StreamInterface) {
throw new \InvalidArgumentException('The $body parameter to ServerRequestCreator::fromArrays must be string, resource or StreamInterface');
}

return $serverRequest->withBody($body);
}

/**
* Implementation from Zend\Diactoros\marshalHeadersFromSapi().
*/
public function getHeadersFromServer(array $server): array
{
$headers = [];
foreach ($server as $key => $value) {
// Apache prefixes environment variables with REDIRECT_
// if they are added by rewrite rules
if (0 === strpos($key, 'REDIRECT_')) {
$key = substr($key, 9);

// We will not overwrite existing variables with the
// prefixed versions, though
if (array_key_exists($key, $server)) {
continue;
}
}

if ($value && 0 === strpos($key, 'HTTP_')) {
$name = strtr(strtolower(substr($key, 5)), '_', '-');
$headers[$name] = $value;

continue;
}

if ($value && 0 === strpos($key, 'CONTENT_')) {
$name = 'content-'.strtolower(substr($key, 8));
$headers[$name] = $value;

continue;
}
}

return $headers;
}

private function getMethodFromEnv(array $environment): string
Expand Down
52 changes: 52 additions & 0 deletions src/ServerRequestCreatorInterface.php
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Nyholm\Psr7Server;

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;

interface ServerRequestCreatorInterface
{
/**
* Create a new server request from the current environment variables.
* Defaults to a GET request to minimise the risk of an \InvalidArgumentException.
* Includes the current request headers as supplied by the server through `getallheaders()`.
*
* @throws \InvalidArgumentException If no valid method or URI can be determined.
*/
public function fromGlobals(): ServerRequestInterface;

/**
* Create a new server request from a set of arrays.
*
* @param array $server Typically $_SERVER or similar structure.
* @param array $headers Typically the output of getallheaders() or similar structure.
* @param array $cookie Typically $_COOKIE or similar structure.
* @param array $get Typically $_GET or similar structure.
* @param array $post Typically $_POST or similar structure.
* @param array $files Typically $_FILES or similar structure.
* @param StreamInterface|resource|string|null $body Typically stdIn
*
* @throws \InvalidArgumentException If no valid method or URI can be determined.
*/
public function fromArrays(
array $server,
array $headers = [],
array $cookie = [],
array $get = [],
array $post = [],
array $files = [],
$body = null
): ServerRequestInterface;

/**
* Get parsed headers from ($_SERVER) array.
*
* @param array $server Typically $_SERVER or similar structure.
*
* @return array
*/
public function getHeadersFromServer(array $server): array;
}
54 changes: 51 additions & 3 deletions tests/ServerRequestCreatorTest.php
Expand Up @@ -323,7 +323,7 @@ public function testNormalizeFilesRaisesException()
$this->creator->fromArrays(['REQUEST_METHOD' => 'POST'], [], [], [], [], ['test' => 'something']);
}

public function testFromGlobals()
public function testFromArrays()
{
$server = [
'PHP_SELF' => '/blog/article.php',
Expand Down Expand Up @@ -380,11 +380,11 @@ public function testFromGlobals()
],
];

$server = $this->creator->fromArrays($server, [], $cookie, $get, $post, $files);
$server = $this->creator->fromArrays($server, [], $cookie, $get, $post, $files, 'foobar');

$this->assertEquals('POST', $server->getMethod());
$this->assertEquals(['Host' => ['www.blakesimpson.co.uk']], $server->getHeaders());
$this->assertEquals('', (string) $server->getBody());
$this->assertEquals('foobar', (string) $server->getBody());
$this->assertEquals('1.0', $server->getProtocolVersion());
$this->assertEquals($cookie, $server->getCookieParams());
$this->assertEquals($post, $server->getParsedBody());
Expand Down Expand Up @@ -474,4 +474,52 @@ public function testGetUriFromGlobals($expected, $serverParams)
{
$this->assertEquals(new Uri($expected), NSA::invokeMethod($this->creator, 'createUriFromArray', $serverParams));
}

/**
* Test from zendframework/zend-diactoros.
*/
public function testMarshalsExpectedHeadersFromServerArray()
{
$server = [
'HTTP_COOKIE' => 'COOKIE',
'HTTP_AUTHORIZATION' => 'token',
'HTTP_CONTENT_TYPE' => 'application/json',
'HTTP_ACCEPT' => 'application/json',
'HTTP_X_FOO_BAR' => 'FOOBAR',
'CONTENT_MD5' => 'CONTENT-MD5',
'CONTENT_LENGTH' => 'UNSPECIFIED',
];

$expected = [
'cookie' => 'COOKIE',
'authorization' => 'token',
'content-type' => 'application/json',
'accept' => 'application/json',
'x-foo-bar' => 'FOOBAR',
'content-md5' => 'CONTENT-MD5',
'content-length' => 'UNSPECIFIED',
];

$this->assertSame($expected, $this->creator->getHeadersFromServer($server));
}

/**
* Test from zendframework/zend-diactoros.
*/
public function testMarshalsVariablesPrefixedByApacheFromServerArray()
{
// Non-prefixed versions will be preferred
$server = [
'HTTP_X_FOO_BAR' => 'nonprefixed',
'REDIRECT_HTTP_AUTHORIZATION' => 'token',
'REDIRECT_HTTP_X_FOO_BAR' => 'prefixed',
];

$expected = [
'authorization' => 'token',
'x-foo-bar' => 'nonprefixed',
];

$this->assertEquals($expected, $this->creator->getHeadersFromServer($server));
}
}

0 comments on commit a9e7240

Please sign in to comment.