Code Monkey home page Code Monkey logo

psr7-middlewares's Issues

Https Redirect includes port 80

I'm trying to use Https middleware with a Slim 3 application.

When I attach the middleware to a route, the https redirection is happening, however, the URI that I'm being redirected to is https://my-dev-site.local:80/rest/of/the/path.

Now, I know where the 'problem' is, and I have found a seemingly easy fix for it, but I'm not sure of whether the fault lies with the Https middleware or if it is Slim's Psr\Http\Message\UriInterface implementation.

When the new URI is created with the https scheme on Line 78 of Https.php, only the scheme of the URI is updated $uri = $uri->withScheme('https');. This leave the port of the URI set to its original value of 80. When this newly created URI is cast to a string by the RedirectResponseTrait, it generates a URI with a scheme of https and a port of 80. It is happening because the Slim UriInterface implementation compares the scheme and port to see if they are 'standard'. If the scheme is http and the port is 80, it does not include in port the string cast. Likewise, if the scheme is https and the port is 443 a port is not included in the string cast.

In this case, since the scheme is being changed, but not the port, Slim's Uri class is returning the non-standard https port of 80 in the string URI.

The simple solution to this is to update Https middleware to also change the port to 443. So, line 78 of Https.php becomes $uri = $uri->withScheme('https')->withPort(443).

If this is acceptable, I can do a pull request for this small change, but I wanted to bring it up here first to see if there could be any unforeseen consequences caused by this.

Use statement for RuntimeException required in class ContainerTrait

A use statement needs to be added to class ContainerTrait for the RuntimeException like shown below:

<?php

namespace Psr7Middlewares\Utils;

use Interop\Container\ContainerInterface;
use InvalidArgumentException;
use RuntimeException;

otherwise the RunTimeException class will not be found when thrown as it is looked up in local namespace.

Question about Cache Middleware

Hello Oscar,

I've used the cache middleware of release 3.19, and I've a question about multi-device usage !

The cache key is specified there
https://github.com/oscarotero/psr7-middlewares/blob/master/src/Middleware/Cache.php#L121

That means the cache in PSR-6 pool is shared between all clients (desktop / mobile / tablet)

But the 304 is sent back to client device to tell it to use its device cache version.
If a desktop client create a cache in PSR-6 pool (server side) it then use it by mobile client (that sould not probably have a cache version, if it's first call)

Perharps an issue ? Or did I'm wrong and missed something !

Thanks in advance for your answer.
Laurent

Defective unit tests not marked as risky.

@abacaphiliac While working on changes to Payload for #50 I took a closer look at the unit tests for Payload. It seems that something is going wrong there.

The callback defined in testJsonObjectPayload is never actually triggered, thus never hitting the asserts defined in there. Reason is that the Transformer throws a DomainException("Syntax Error"). Which, if you look at the JSON closely is correct: {"buz",true}} should be {"buz":true}}. Took quite some time to figure this one out :)

The bigger problem, and the reason I'm making this an issue instead of fixing it in a PR directly, is that we apparently run unit tests which trigger no assertions at all, and are still considered valid. I'd like to propose adding beStrictAboutTestsThatDoNotTestAnything="true" to the phpunit.xml configuration to deal with this.

AuraRouter curl stuck at 404 not found.

I try to use AuraRouter with the middlewares, and it works fine if the routing exists. However, curl will not stop connection when the response is 404, 405, 406. I check the codes and find that there is no response in the code. I think we should at least add $response->getBody()->write("\n") or even better let us configure our own response message on 404, 405, 406.

oscarotero/psr7-middlewares/src/Middleware/AuraRouter.php

        if (!$route) {
            $failedRoute = $matcher->getFailedRoute();

            switch ($failedRoute->failedRule) {
                case 'Aura\Router\Rule\Allows':
                    return $response->withStatus(405); // 405 METHOD NOT ALLOWED

                case 'Aura\Router\Rule\Accepts':
                    return $response->withStatus(406); // 406 NOT ACCEPTABLE

                default:
                    return $response->withStatus(404); // 404 NOT FOUND
            }
        }

Bug: 502 bad gateway on 3.10

The new update got installed with composer update. But I got a strange 502 bad gateway error for my ajax requests.

I couldn't figure out the problem at first, so I tried to rollback some composer updates and it looks like that the problem is gone when I rolled back to the previous 3.9.3 version.

The strange thing is that normal (none-ajax) request are doing fine.

This is my dispatcher with the used middleware. Please let me know if you need more information.

$relay = new RelayBuilder();

$dispatcher = $relay->newInstance([

    Middleware::FormatNegotiator(),

    //Adds the php debug bar
    Middleware::debugBar($debugbar),

    Middleware::LeagueRoute()
        ->router($router) //The RouteCollection instance
]);

$response = $dispatcher(ServerRequestFactory::fromGlobals(), new Response());

(new Zend\Diactoros\Response\SapiEmitter)->emit($response);

Middleware request: CSRF Protection

Hi!

Thanks for the nice library. I would like to suggest some middlewares, I will make a seperate issue for each request.

It would be nice to have middleware for CSRF protection. I think the Slim-Csrf has support for psr-7. https://github.com/slimphp/Slim-Csrf

Also, I would like to build some middlewares myself to help expand the support for more middleware. But at this moment I am not sure how to do this exactly. Could you give me some tips?

Closed

How embarrassing... trying to search issues... ignore this ๐Ÿ˜…

Csrf middleware is not fully PHP 5 compatible

Hello,

I've recently used Csrf Middleware with PHP 5.6 and cannot run it due to generateTokens() function.

random_bytes is only available since PHP 7.0

I suggest to use openssl extension such as :

        if (version_compare(PHP_VERSION, '7.0', 'ge')) {
            $index = self::encode(random_bytes(18));
            $token = self::encode(random_bytes(32));
        } else {
            $index = self::encode(openssl_random_pseudo_bytes(18));
            $token = self::encode(openssl_random_pseudo_bytes(32));
        }

What do you think of such solution ?

Would traits better replace the static class?

I am assuming that the Middleware class is basically a collection of functions, which are collected into a class instance?

$request = Middleware::setAttribute($request, self::KEY, $this->basePath);

// better as

use RequestAttributesHelperTrait;

$request = $this->setRequestAttribute($request, self::KEY, $this->basePath);

Using this as an example, it would be (IMO) better to have a set of traits to allow this functionality to be implanted into middlewares, rather than relying on a static class. Obviously backwards compatibility is an issue, so the static class can use the traits and still implement it's own methods.

When it comes to the factory method, I think an abstract factory class would be more apt, which can also have a helper trait to allow injecting itself into middleware instances that require it.

What do you think about an architectural change like this? Being that it is such a large change, it could be argued into a version release, but having a good backwards compatibility, it could be a feature release. I don't mind working on it, as I really like this codebase and want to use it, but I just can't bring myself to allow statics into my codebase :D

Allow to customize the key used by the middlewares in the request attributes

For example:

use Psr7Middlewares\Middleware\AuraSession;

AuraSession::setKey('_AppSession');

This allows to prevent conflicts and use static functions to get the values:

use Psr7Middlewares\Middleware\AuraSession;

function ($request, $response, $next) {
    $session = $request->getAttribute('_AppSession');
    //this is the same than:
    $session = AuraSession::getSession($request);
}

JsonDecoder

Attention! This code is draft! not tested! Just suggestion

<?php

namespace Psr7Middlewares\Middleware;

use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

class JsonDecoder
{
    public function __invoke(ServerRequestInterface &$request, ResponseInterface $response, callable $next)
    {
        if (0 === strpos($request->getHeaderLine('content-type'), 'application/json')) {
            // reset error
            json_encode(null);

            $json = $request->getBody()->getContents();
            $json = json_decode($json, true);

            if (JSON_ERROR_NONE != json_last_error()) {
                throw new InvalidArgumentException(sprintf(
                    'Unable to decode data from JSON in %s: %s',
                    __CLASS__,
                    json_last_error_msg()
                ));
            }

            $method = $request->getMethod();
            if ($method == 'GET') {
                $request = $request->withQueryParams($json);
            } else if (in_array($method, ['POST','PUT','PATCH'])) {
                $request = $request->withParsedBody($json);
            }
        }
        ...
    }
}

Feature request: custom middleware

As far as I can see the only way to add middleware is to add it to the middleware folder.

I thought it would be nice to also add a configuration option to also include middleware from a different custom location.

This way you can also add middleware from other sources (without struggling with updates/composer). And it's easier to build/change middleware for application specific purposes.

For example: I would like to have a middleware which will check my database if a user is already connected. I don't think that is interesting for anyone else :)

BlockSpam default path to spammers.txt is wrong

The BlockSpam middleware is looking for a wrong path a default

Actually looking for :

__DIR__.'/../../../../vendor/piwik/referrer-spam-blacklist/spammers.txt'
mean
/Users/vincent/Work/hello-world/vendor/oscarotero/psr7-middlewares/src/Middleware/../../../../vendor/piwik/referrer-spam-blacklist/spammers.txt

Real path is :

__DIR__.'/../../../../piwik/referrer-spam-blacklist/spammers.txt'
mean
/Users/vincent/Work/hello-world/vendor/oscarotero/psr7-middlewares/src/Middleware/../../../../piwik/referrer-spam-blacklist/spammers.txt

Firewall middleware needs ClientIp executed before

Hello,

I use Slim3 and I try to use the firewall but I've an error :

use Psr7Middlewares\Middleware;

// Firewall
$app->add(Middleware::ClientIp());
$app->add(Middleware::Firewall(['37.97.90.193']));

ClientIp has launch before Firewall. Why I've this error ?

Thanks

MethodOverride improvements

In my adventures, I tend to find that the use case for overriding an HTTP method comes from web browsers where we all know there is poor support for anything other than POST and GET.

I'm just wondering how useful this middleware package is when solely relying on a header to do the overriding? Generally, clients that can set headers can also make requests with deliberate HTTP methods.

Would it be possible to have this upgraded to use a POST form field, and query-string parameter alongside the header?

$getUrl = "example.com?http-method-override=HEAD";

$postBody = [
    "http-method-override" => "PUT"
];

It would become so much more useful in the wild with additions like this.

Custom Middleware

Can I create my own middleware like this?

class MiddlewareMy extends MiddlewareBase
{
    public function handle(...) 
    {

    } 
}

Does this project follow semver?

I'm just wondering if this project follows semantic versioning?

I ask because in version 3.14 there was a changed introduced in the Honeypot middleware that caused the default behavior of the middleware to change.

This change caused the contact form on my website to stop working.

I only ask because if it doesn't, I need to lock my composer version to a specific version rather than doing the "standard" ^3.0 in composer. Following semantic versioning, I would not have expected to have what is in actuality a BC break when going from 3.13.1 to 3.16.1.

Thanks for this library. I really like it.

MiddlewareInterface

Hello,

I noticed your middleware is not compatible with Interop\Http\ServerMiddleware\MiddlewareInterface.
Will you upgrade your package?

Thanks,
Best regards,

Adding extra slashes after domain name in url allows you to bypass JWT Authentication

The following array was passed to JwtAuthentication class constructor:

$options = [
    "secret" => $_ENV["JWT_SECRET"],
    "path" => ["/api/v1"],
    "passthrough" => ["/api/v1/login"]
]

Sending an HTTP request to "http://localhost/api/v1/restricted" returns HTTP 401 Unauthorized but for some reason I am able to bypass JWT authentication by adding one or more extra slashes after the domain name. e.g. "http://localhost//api/v1/restricted"

https middleware

Hello,

Actually it's not possible to activate or deactivate https middleware by passing an argument like for www middleware does :

Middleware::Www(true)

This is really useful when switching from a development to production environment.

Is it possible to add this function?

Thank you so much.

Return multiple middlewares in ::create()

It'd be cool if in the closure for ::create() i could return an array of middlewares instead of just one new one. Example use case would be something like

Middleware::create("/admin", function() {
    return [
        new AuthMiddleware(),
        new AdminMiddleware()
    ];
}

Expose Middleware

Feature

<?php
namespace Psr7Middlewares\Middleware;

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
 * Middleware to remove php information
 */
class Expose
{
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
    {
        $response = $response->withoutHeader('X-Powered-By');

        return $next($request, $response);
    }
}

HTTPS terminated at load balancer

So I found the following issue when implementing my site. I had originally tested it on servers that were using local self-signed certs, so everything was great.

$app->add(Middleware::TrailingSlash(false)->redirect(301));
$app->add(Middleware::Https());

HTTPS
Because I moved to a system that was terminating the SSL on the load balancer the HTTPS middleware was causing infinite redirects. Its not really a bug but took me a hot second to figure out what the heck was going on.

TrailingSlash
Then because the SSL is terminated when TrailingSlash would fire, it would send the redirect back but with an http:// protocol because that is how the request came in. As far as I'm aware the following headers are somewhat of a standard for this type of situation. Do you think it would be prudent to look for these headers and if the they exist change the URI? You could maybe if just add it as a chained method that would checkHTTPSForward or something.

HTTP_X_FORWARDED_PROTO: https
HTTP_X_FORWARDED_PORT: 443

Remove dependency on container-interop

I highly recommend adopting the Resolver pattern instead of depending container-interop. The interface looks like this:

interface Resolver
{
    /**
     * @param string
     * @return object
     */
    public function resolve($spec);
}

Make all middleware immutable

There are a number of configuration methods in these middleware that prevent them from being treated as immutable, for example Payload::associative which could be written as:

public function withAssociative($setting)
{
    $copy = clone $this;
    $copy->associative = (bool) $setting;
    return $copy;
}

FielTrait::getFilename ignores query parameters

Currently a page is cache only depending on its URI path, ignoring all query parameters. Which means if you have per examples query parameters to sort a table, or switch tabs, they all serve the same cached page.

FormatNegotiator - hard coded priorities?

Within FormatNegotiator, the negotiateHeader function call sends the hardcoded $headers as the $priority parameter to the Negotiator instance.

Therefore, if the Accept header is set to "*/*", the result will always be "html" regardless of what is specified as the default format.

//Code
Middleware::FormatNegotiator()
    ->defaultFormat('json')

//Request header
Accept: */*

//Result: 
FormatNegotiator::getFormat($request) === "html"

Negotiator allows you to specify a list of priorities. Could this functionality be emulated in FormatNegotiator?

For example:

//Code
Middleware::FormatNegotiator()
    ->setPriorities(['json', 'zip'])

//Request header
Accept: */*

//Result: 
FormatNegotiator::getFormat($request) === "json"

Split into separate discrete packages?

I had some recollection of this being discussed, but I don't see it in the issue
tracker, so I figure I'd raise it here. I assume there has been some discussion
on this, so at minimum, I think it would be nice to have the record of it here.

Firstly, I'm a fan of minimalism and the 'do one thing and do it right' ethos.
In my opinion, it would be nice to have this collection split into separate,
discrete packages
. Things like the Authentication middleware might be grouped
together, but things of disparate concerns with varying requirements
could/should be separate.

I think the most obvious reason is that a handful of these have real
requirements (i.e. AuraRouter), which are only listed as suggestions. The
ability to actually require the dependency (including version requirements)
seems like an obvious benefit.

Additionally, it just doesn't feel right to me to require the whole thing to
use a single component. It would be nice to glance at componser.json and have
at least some idea of what functionality is being leveraged. It's also strange
to continually get updates which are possibly unrelated to the utilized
functionality.

I also assume (possibly without cause) that release versioning is/will-become
cumbersome with this paradigm. Given two components of unrelated concerns,
should not one be able to change it's public API and require a 1.0 release
without affecting the other?

I would register my vote for separate vendor prefix with discrete packages (eg
oscarware/aura-router, oscarware/auth, etc.). If absolutely necessary, they
could require a common utility package. For those desiring the "all-in-one"
paradigm, an additional package could be created which simply requires the
discrete ones.

Thoughts?

JSON Schema incompatible with Slim Framework

The JSON Schema middleware does not work with Slim Framework. Reason is that it relies on the Payload middleware to have getParsedBody to yield a stdClass object, using the newly added forceArray=false option on Middleware\Payload.

Slim's Request object has body parsing built-in. Unfortunately they force the JSON payload into an associative array (as documented in their manual) Our Payload MW currently does the following check to decide whether or not we should parse the body:

if (*!$request->getParsedBody()* && in_array($request->getMethod(), [...]

Since getParsedBody will hit Slim's version, we're basically stuck with whatever parsed body they provide. I've come up with three ways to deal with this:

Option 1: "Not our problem", have the developer deal with it in their Framework. In effect this would mean registering a custom "body parser" in Slim using registerMediaTypeParser to overwrite the default parser for application/json media types.

Option 2: Instead of bailing out in JSON Schema if the parsed body is not an object, do an if-array-then-cast-to-object, which will yield the stdClass we need.

Option 3: Fix it in Middleware::Payload by (optionally?) having it overwrite previously parsed bodies. Slight loss of efficiency, but ultimately it does give us more control over the request.

Would like your opinion on this before forging ahead with a PR. My preference would be option 3, under the following rationale: By adding the Payload middleware to your stack you're explicitly handing us responsibility to handle the request body, since apparently your current stack is not capable of dealing with the provided payload... it would make sense then not to rely on any previous parsed body contents.

I'll also raise this issue over at Slim to get their opinion on this.

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.