Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Copy matched parameters for HEAD requests #74

Merged
merged 3 commits into from May 10, 2018
Merged

Copy matched parameters for HEAD requests #74

merged 3 commits into from May 10, 2018

Conversation

geerteltink
Copy link
Member

@geerteltink geerteltink commented May 3, 2018

Someone is spamming my site with HEAD requests and they are causing exceptions. I don't care much about the spamming, I'm more interested in why the request fails. It turns out for a normal GET request, the matched route parameters are copied into the request as attributes in the RouteMiddleware. The ImplicitHeadMiddleware runs after the RouteMiddleware and it tries to match the request again as a HEAD request, however it doesn't copy the matched route parameters into the request. This causes the handler to load it as a GET request, but it doesn't get the parameters and thus throws exceptions. I could check for an existing id but without a valid id, the GET route wouldn't be matched anyway and so shouldn't the HEAD request.

There are 2 solutions I can think of.

  1. Always use the RouteResult to get matched parameters. But doing that, it means that modules can't be reused outside Expressive as other frameworks don't have a RouteResult.
  2. Copy the parameters like RouteMiddleware does so the handler doesn't need to check if it is a GET or HEAD request and $request->getAttribute('id') can be used.

Unless someone has a better idea, I'll go for solution 2.

  • Are you fixing a bug?
    • Detail how the bug is invoked currently.
    • Detail the original, incorrect behavior.
    • Detail the new, expected behavior.
    • Base your feature on the master branch, and submit against that branch.
    • Add a regression test that demonstrates the bug, and proves the fix.
    • Add a CHANGELOG.md entry for the fix.

@geerteltink geerteltink added the bug label May 3, 2018

public function testInvokesHandlerWithRequestComposingRouteResultAndAttributes()
{
$result = $this->prophesize(RouteResult::class);
Copy link
Member

Choose a reason for hiding this comment

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

From experience it's bad to mock RouteResult. It is easy to mock it wrongly and I think it's better to instantiate it using one of fromRoute or fromRouteFailure. Then the test will be clearer and we can be sure that we have the proper instance.

Copy link
Member Author

Choose a reason for hiding this comment

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

That would mean the other tests are bad as well. This is code I copied from the test before.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, not future-proof, and it should be changed imho. I did some of these changes here:
adb00ca

As this is a new test it should be fixed before merging, and in separate PR we can fix others.

Don't you think that test will be clearer if you use fromRoute or fromRouteFailure to create proper RouteResult ?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a complicated test. I don't have time to update all tests. This issue already took me a some time to debug and fix. I'll see what I can do in the weekend.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not saying you have to fix all other test, just your test. All others can be fixed later on in separate PR.


$parameters = ['foo' => 'bar', 'baz' => 'bat'];
$result = $this->prophesize(RouteResult::class);
$result->isFailure()->willReturn(false);
Copy link
Member

Choose a reason for hiding this comment

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

As commented above. Here you are mocking it because you know what are the internal calls (because you checked them). Why you are not mocking isSuccess method? I think this test is not future proof, so as I suggested above RouteResult should NOT be mocked.

@weierophinney weierophinney merged commit e3d7a18 into zendframework:master May 10, 2018
weierophinney added a commit that referenced this pull request May 10, 2018
weierophinney added a commit that referenced this pull request May 10, 2018
Forward port #75
Forward port #74

Conflicts:
	CHANGELOG.md
@weierophinney
Copy link
Member

Thanks, @xtreamwayz!

@geerteltink geerteltink deleted the hotfix/head-attributes branch May 14, 2018 16:31
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants