Giter Site home page Giter Site logo

psr7-server's Introduction

Helper class to create PSR-7 server request

Latest Version Build Status Code Coverage Quality Score Total Downloads Monthly Downloads Software License

A helper class that can create ANY PSR-7 server request.

Installation

composer require nyholm/psr7-server

Usage

// Instanciate ANY PSR-17 factory implementations. Here is nyholm/psr7 as an example
$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory();

$creator = new \Nyholm\Psr7Server\ServerRequestCreator(
    $psr17Factory, // ServerRequestFactory
    $psr17Factory, // UriFactory
    $psr17Factory, // UploadedFileFactory
    $psr17Factory  // StreamFactory
);

$serverRequest = $creator->fromGlobals();

Other packages

psr7-server's People

Contributors

derrabus avatar drupol avatar edudobay avatar frkinta avatar groruk avatar mindplay-dk avatar mohjive avatar nickdnk avatar nyholm avatar takamichi avatar zegnat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

psr7-server's Issues

Duplicated port in URI

Hi!

I am getting wrong URI when running on localhost with custom port:

<?php declare(strict_types = 1);

require __DIR__ . '/../vendor/autoload.php';

use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7Server\ServerRequestCreator;

$psr17Factory = new Psr17Factory();

$creator = new ServerRequestCreator(
    $psr17Factory,
    $psr17Factory,
    $psr17Factory,
    $psr17Factory
);

$request = $creator->fromGlobals();

echo $request->getUri()->__toString();

GET http://localhost:8000/

http://localhost:8000:8000/

The problem is probably due to mechanism used to create URI in ServerRequestCreator::createUriFromArray(). URI host gets populated with $_SERVER['HTTP_HOST'], but this contains also the port (see for example here: https://stackoverflow.com/a/12046836 ).

I propose two solutions:

  1. strip the port from $_SERVER['HTTP_HOST']
  2. use $_SERVER['SERVER_NAME'] instead - I am not sure about the consequences

I may create a pull request with fix if you want.

Static method in interface?

Any particular reason why getHeadersFromServer is part of ServerRequestCreatorInterface?

It's not like you can call it as ServerRequestCreatorInterface::getHeadersFromServer() - you always have to reference the implementation of a static method... static methods in interfaces don't generally make any sense - possibly except when you're just trying to make sure you implement a static method in the same way in several classes, but even then, it doesn't serve as any kind of abstraction, and you only have one implementation here, so...?

Better Namespaces

Would it not make more sense to have Nyholm\Psr7\Server to follow the other packages you have?

Failed to create UploadedFile when an upload error occurred

The following warning is occurred because trying to create a stream from an empty filename.

Warning: fopen(): Filename cannot be empty

The problem is in createUploadedFileFromSpec() function.
I think that the function should check for upload errors.

private function createUploadedFileFromSpec(array $value)
{
    if (\is_array($value['tmp_name'])) {
        return $this->normalizeNestedFileSpec($value);
    }

    return $this->uploadedFileFactory->createUploadedFile(
        $this->streamFactory->createStreamFromFile($value['tmp_name']),
        (int) $value['size'],
        (int) $value['error'],
        $value['name'],
        $value['type']
    );
}

Scheme detection problem

Recently I was bringing up a site based on Grav, which uses psr7-server/ServerRequestCreator.php directly to prepare a request object for further manipulation. The server I was using had the following peculiarity: it had $_SERVER['REQUEST_SCHEME'] set to http and at the same time $_SERVER['HTTPS'] set to on. All of that while I was using exclusively HTTPS. This caused an occasional problem when a redirection was made to e.g. http://example.com:443/about instead of https://example.com/about. I believe the way the scheme detection works now is a problem, since current code will set scheme as http even though the server also reports $_SERVER['HTTPS'] as being used. I mean this fragment:

if (isset($server['REQUEST_SCHEME'])) {
$uri = $uri->withScheme($server['REQUEST_SCHEME']);
} elseif (isset($server['HTTPS'])) {
$uri = $uri->withScheme('on' === $server['HTTPS'] ? 'https' : 'http');
}

Shouldn't HTTPS header have precedence here? Something like this code here (from https://www.designcise.com/web/tutorial/how-to-check-for-https-request-in-php):

$isHttps = 
    $_SERVER['HTTPS']
    ?? $_SERVER['REQUEST_SCHEME']
    ?? $_SERVER['HTTP_X_FORWARDED_PROTO']
    ?? null
;

$isHttps = 
    $isHttps && (
        strcasecmp('on', $isHttps) == 0
        || strcasecmp('https', $isHttps) == 0
    )
;

or, at least, reverse the order of condition checks?

I think this problem is somewhat related, but not identical to #29.

Duplicate host values in Host header when creating a Psr request from globals

When creating a PSR request from globals, the hostname is set twice in the Host header. This is not allowed according to the RFC:

A server MUST respond with a 400 (Bad Request) status code to any
HTTP/1.1 request message that lacks a Host header field and to any
request message that contains more than one Host header field or a
Host header field with an invalid field-value.

The first hostname is added in the ServerRequest object constructor:

if (!$this->hasHeader('Host')) {
    $this->updateHostFromUri();
}

However, Host header is added again in the ServerRequestCreator class in the fromArrays() function here because it uses the withAddedHeader function:

foreach ($headers as $name => $value) {
    // Because PHP automatically casts array keys set with numeric strings to integers, we have to make sure
    // that numeric headers will not be sent along as integers, as withAddedHeader can only accept strings.
    if (\is_int($name)) {
        $name = (string) $name;
    }
    $serverRequest = $serverRequest->withAddedHeader($name, $value);
}

This results in the following Host header in the Psr request:

Host: hostname.tld, hostname.tld

Header with only numbers seems to cause exception

Hello

Our server received some scripted attack attempts aimed at Wordpress (which we don't run though). These requests have headers that look like this:

0: Accept-Language: en-US,en;q=0.5
1: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36

Which seems to cause the "Header name must be an RFC 7230 compatible string." exception to be thrown. It appears to be because of the header regex not accepting this, in https://github.com/Nyholm/psr7/blob/master/src/MessageTrait.php.

Is this a bug? This approach also causes a 500 to be thrown for a client error, which you'd expect to be a 400. I'm using Slim, so maybe this needs to be fixed there. I just wanted to check in here and see if you had any feedback before I bring it up with Slim.

Edit: It's thrown for any header that consists only of numbers.

Uri::withPort + numeric strings

I came across an issue whilst following https://github.com/php-runtime/psr-17#psr-7-and-psr-15-runtime to use Slim's psr-7 implementation.
At least when running with php-fpm + nginx, $_SERVER['HTTP_PORT'] is populated with a numeric string, eg 8080. https://github.com/Nyholm/psr7-server/blob/master/src/ServerRequestCreator.php#L279 passes that string through to a UriInterface, which with Sim's implementation results in "Uri port must be null or an integer between 1 and 65535 (inclusive)" (because it fails an is_integer check). Using nyholm/psr7 works though, as it casts the string value to an int.
I was going to raise this as an issue against slim/psr-7, but on reading the http-mesage spec it looks like withPort should accept null|int. I think the more correct fix is that ServerRequestCreator should ensure that it is indeed passing in an integer or null.

Filter headers consisting only of whitespace before creating a ServerRequest

As documented in this issue, apache_request_headers()/getallheaders() isn’t guaranteed to return valid header data, even when the request made was valid. Specifically, in some server configurations, an Expect: 100-continue header (sent by e.g. cURL when making large file upload requests) is removed by converting each character in the key and value to a space, rather than just ignoring the header.

I propose that ServerRequestCreator::fromGlobals() should filter out the following invalid header data before creating a ServerRequestInterface:

  • Key/value pairs from getallheaders() where both the key and value consist entirely of whitespace
  • Key/value pairs from $_SERVER['HTTP_*'] where the header key consists only of underscores, and the value only contains whitespace

I’d be happy to work on a PR for this if the maintainers agree that it’s a necessary fix.

Empty file upload gives fatal error in PHP 8.0

I have an HTML form with an optional <input type="file"> field.

There is no problem with PHP 7.1-7.4, but with PHP 8.0 I get the following error.

Uncaught ValueError: Path cannot be empty in /Users/gr4376/Projects/webtrees/vendor/nyholm/psr7/src/Factory/Psr17Factory.php:40
Stack trace:
#0 .../vendor/nyholm/psr7/src/Factory/Psr17Factory.php(40): fopen('', 'r')
#1 .../vendor/nyholm/psr7-server/src/ServerRequestCreator.php(216): Nyholm\Psr7\Factory\Psr17Factory-&gt;createStreamFromFile('')
#2 .../vendor/nyholm/psr7-server/src/ServerRequestCreator.php(188): Nyholm\Psr7Server\ServerRequestCreator-&gt;createUploadedFileFromSpec(Array)
#3 .../vendor/nyholm/psr7-server/src/ServerRequestCreator.php(98): Nyholm\Psr7Server\ServerRequestCreator-&gt;normalizeFiles(Array)
#4 .../vendor/nyholm/psr7-server/src/ServerRequestCreator.php(71): Nyholm\Psr7Server\ServerRequestCreator-&gt;fromArrays(Array, Array, Array, Array, Array, Array, Resource id #7)
#5 .../index.php(55): Nyholm\Psr7Server\ServerRequestCreator->fromGlobals()

This is because fopen('') gives a warning in PHP <=7.4, but a fatal error in PHP 8.0.

See https://3v4l.org/cgYav

Stop using UriFactory

If we rewrite this function so it does not use the UriFactory but returning a URI string instead. Then we could pass that string directly to the ServerRequestFactory.

Is that a refactoring we want to do?

Fix tests fixtures

From php.net:

'HTTPS'
    Set to a non-empty value if the script was queried through the HTTPS protocol. 

This PR

  • Fix the behavior of the HTTPS key property.
  • Do not add tests
  • Reduce cyclomatic complexity of the of ServerRequestCreator::createUriFromArray() method.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.