Skip to content

Fix the request target in PSR7 Request #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

mtibben
Copy link

@mtibben mtibben commented May 3, 2017

The request target is not being preserved correctly when using this library. This is because the query string is normalized, and we're not populating the PSR-7 request with the actual request target.

This is important for things like http signatures which uses the request target as an input to sign a request.

@mtibben mtibben changed the title Add test for request target Fix the request target in PSR7 Request May 4, 2017
@mtibben
Copy link
Author

mtibben commented May 4, 2017

I've added a fix for the issue.

The failing tests here are also failing on master.

@xabbuh
Copy link
Member

xabbuh commented May 4, 2017

I opened #31 to fix the test suite.

@fabpot
Copy link
Member

fabpot commented May 4, 2017

@mtibben You can now rebase to validate that tests pass now.

@mtibben
Copy link
Author

mtibben commented May 4, 2017 via email

@mtibben
Copy link
Author

mtibben commented May 14, 2017

Rebased, and tests are passing @fabpot

@@ -55,7 +55,7 @@ public function createRequest(Request $symfonyRequest)
$request = new ServerRequest(
$server,
DiactorosRequestFactory::normalizeFiles($this->getFiles($symfonyRequest->files->all())),
$symfonyRequest->getUri(),
$symfonyRequest->getSchemeAndHttpHost().$symfonyRequest->getRequestUri(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change really required? Shouldn't the result be the same?

Copy link
Author

@mtibben mtibben May 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getUri creates a URL in a very indirect way. This will likely be a problem due to the way Symfony requests normalise different parts of the URL. In comparison, getRequestUri is much more direct, you can see in prepareRequestUri how the URL comes directly from the superglobals or headers.

As we're dealing with a conversion between request types, we need to use the cleanest data we can when constructing the PSR7 request. Otherwise we can get a URL different to the original

@@ -65,6 +65,7 @@ public function createRequest(Request $symfonyRequest)
->withCookieParams($symfonyRequest->cookies->all())
->withQueryParams($symfonyRequest->query->all())
->withParsedBody($symfonyRequest->request->all())
->withRequestTarget($symfonyRequest->getRequestUri())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary when we already pass the full URI to the constructor?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that a HTTP request begins with a request target (e.g GET /request-target?query=string) not a URL.

In the same way, the PSR-7 Request interface does not mention URLs or constructors. It only knows about request targets. Therefore, I think we should be explicit about setting the request target correctly using withRequestTarget rather than relying on a particular implementation's constructor

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we are dealing with a concrete implementation here. And if its constructor is not working as expected (which we should check) the implementation should be fixed instead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep I understand what you're saying, I was thinking the same myself. Yet when I looked at the implementation I thought it best to be explicit here. This implementation tokenizes the URL, and pieces together a request target if it is not set explicitly. By providing the request target string, you're giving the implementation the correct data - unfortunately the constructor is not giving you that opportunity. https://github.com/zendframework/zend-diactoros/blob/master/src/RequestTrait.php#L124-L129

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact tests fail without this line, exactly for this reason

Testing Symfony PSR-7 HTTP message Bridge Test Suite
F............                                                     13 / 13 (100%)

Time: 89 ms, Memory: 4.00MB

There was 1 failure:

1) Symfony\Bridge\PsrHttpMessage\Tests\Factory\DiactorosFactoryTest::testCreateRequest
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'/testCreateRequest?foo=1&bar[baz]=42'
+'/testCreateRequest?foo=1&bar%5Bbaz%5D=42'

/Users/michael/src/github.com/mtibben/psr-http-message-bridge/Tests/Factory/DiactorosFactoryTest.php:87
/Users/michael/src/github.com/mtibben/psr-http-message-bridge/vendor/symfony/phpunit-bridge/bin/.phpunit/phpunit-5.7/phpunit:5

FAILURES!
Tests: 13, Assertions: 63, Failures: 1.

@mtibben
Copy link
Author

mtibben commented Jun 4, 2017

Any further feedback on this @xabbuh @fabpot ?

@xabbuh
Copy link
Member

xabbuh commented Jun 5, 2017

I did not have the time to dig deeper, but I would prefer to first check why the ServerRequest class behaves this way and if this isn't a bug that needs to be fixed there.

@mtibben
Copy link
Author

mtibben commented Dec 18, 2017

Any further feedback on this @xabbuh? I don't believe ServerRequest is the issue, the issue is Request::getUri (see #30 (comment))

@xabbuh
Copy link
Member

xabbuh commented Dec 18, 2017

I tried to debug this and IIRC the factory behaves differently depending on how you pass the request URI (through the constructor or with withRequestTarget()). Thus, I think this change looks indeed valid.

@fabpot
Copy link
Member

fabpot commented Dec 19, 2017

Thank you @mtibben.

@fabpot fabpot closed this in c2b7579 Dec 19, 2017
mtibben added a commit to 99designs/http-signatures-php that referenced this pull request Oct 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants