Skip to content

Track redirect HTTP status codes#1711

Merged
sagikazarmark merged 9 commits intoguzzle:masterfrom
mallardduck:track_redirect_codes
Jan 15, 2017
Merged

Track redirect HTTP status codes#1711
sagikazarmark merged 9 commits intoguzzle:masterfrom
mallardduck:track_redirect_codes

Conversation

@mallardduck
Copy link
Copy Markdown
Contributor

Using a similar technique to the current Redirect History feature this PR adds support for tracking the HTTP status codes in a new: 'X-Guzzle-Redirect-Status-History' header.

This PR was created in response to #1710

Comment thread src/RedirectMiddleware.php Outdated
$promise,
(string) $nextRequest->getUri()
(string) $nextRequest->getUri(),
(int) $response->getStatusCode()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there any added value in casting it to int? It will become string anyway. If ou just followed the pattern: the URI needs to be casted so that the URI object becomes string.

Comment thread src/RedirectMiddleware.php Outdated
$statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
array_unshift($historyHeader, $uri);
array_unshift($statusHeader, $statusCode);
return $response->withHeader(self::HISTORY_HEADER, $historyHeader)->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you split this line to multiple ones?

@sagikazarmark
Copy link
Copy Markdown
Member

Okay, you bought me.

Can you please add some tests?

@mallardduck
Copy link
Copy Markdown
Contributor Author

Sure thing, I can totally add tests!
I'll work up some tests tonight and get an updated PR sometime over the weekend.

...simple enough, this add the requested tests for the new redirect status code history header.
@mallardduck
Copy link
Copy Markdown
Contributor Author

@sagikazarmark I think this should be good to go as I've addressed your feedback and created tests. Let me know if you'd like any other adjustments to be made first!

Comment thread src/RedirectMiddleware.php Outdated
$promise,
(string) $nextRequest->getUri()
(string) $nextRequest->getUri(),
(string) $response->getStatusCode()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am failing to see why we need to do any casting here. As said getUri returns an object which MUST be casted to string, but the status code is scalar.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry about that, I guess I was a little confused initially. Totally get your point now tho.

Update PR incoming....

@sagikazarmark
Copy link
Copy Markdown
Member

I have one last comment, apart from that good to go.

@sagikazarmark
Copy link
Copy Markdown
Member

Okay, the code looks good to me, there is only one final thought: Right now we store status code, and next URL pairs, which means the status code belongs to the previous request, which returned the appropriate new location.

Not sure if it can be confusing or we should document it (since the middlewares are not documented, somewhere in the code).

WDYT?

@mallardduck
Copy link
Copy Markdown
Contributor Author

That's an excellent point!

As you've suggested I think adding comments in the code could be a good option. Alternatively I was thinking this could be added to the FAQ doc?

I'm not sure how common of a question "Why can't I track redirects with Guzzle?" actually is, but maybe this information could fit there? If not that exact question maybe one similar to it?

I also just realized that I should definitely update the request-options file as it contains info on the currently provided header.


I'll update that file and add some comments to the code; I may even include my example of how I track the full redirect path. From there we can evaluate if that's enough information!

@mallardduck
Copy link
Copy Markdown
Contributor Author

I've updated the relevant request-options section in the documents, please take a look and let me know your thoughts!

I've also included an example in the FAQ file that's useful for users looking to consume both headers as a single item. This can be used to merge HTTP status codes with their respective request URIs.

Copy link
Copy Markdown
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

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

Apart from a few wording comments, perfect 👍

Comment thread docs/faq.rst Outdated
$client = new GuzzleHttp\Client(['expect' => false]);

How can I track a redirected requests HTTP codes?
============================================
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should be as long as the title

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Didn't realize that, I'll get that updated!

Comment thread docs/faq.rst Outdated
How can I track a redirected requests HTTP codes?
============================================

You can enable the `track_redirects` option which will enable Guzzle to track
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This first sentence with double "enabled" sounds a little bit weird...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe say "You can enable tracking the redirected URL and the status code via the ... option"

Comment thread docs/faq.rst Outdated

You can enable the `track_redirects` option which will enable Guzzle to track
any redirected URI and status code. Each redirected URI will be stored in the
``X-Guzzle-Redirect-History`` header and each Response Code will be stored in
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's say status code instead of Response Code

Comment thread docs/faq.rst Outdated
``X-Guzzle-Redirect-History`` header and each Response Code will be stored in
the ``X-Guzzle-Redirect-Status-History`` header.

The ``X-Guzzle-Redirect-History`` header will exclude the initial request's URI
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of the header names we could say "the URL history" and "the status code history". Just to avoid duplication. But I am open to other suggestions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This sounds good to me and seems to make it easier to read.

Comment thread docs/faq.rst Outdated

The ``X-Guzzle-Redirect-History`` header will exclude the initial request's URI
and the ``X-Guzzle-Redirect-Status-History`` header will exclude the final
response code. With this in mind you should easily be able to track a requests
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

status code

Comment thread docs/faq.rst Outdated
$redirectCodeHistory = $response->getHeader('X-Guzzle-Redirect-Status-History'); // retrieve Redirects HTTP Status history

// Add the initial URI requested to the URI history
$reversedUriHistory = array_reverse($redirectUriHistory); // First we reverse the array items
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How about using array_unshift instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

xD yep should have thought about that.

lately I've been using collections a lot and converted that logic into this. (there's no unshift for the collecitons i've been using)

Comment thread docs/faq.rst
// (Optional) Combine the items of each array into a single result set
$fullRedirectReport = [];
foreach ($redirectUriHistory as $key => $value) {
$fullRedirectReport[$key] = ['location' => $value, 'code' => $redirectCodeHistory[$key]];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What should be the first item here? IMO it should be the first URL if any, but currently it's the last.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess I'm a little unsure on this to be honest. I read the comments in the middleware about using array_unshift there due to ordering of codes....however when I execute this code I am provided the same order of redirects as I see in curl.

Using the faq code with this patch I am provided with:

[{"location":"https:\/\/grandmascookieblog.com\/cloud.php","code":302},{"location":"http:\/\/www.liquidweb.com\/cloudsites\/","code":301},{"location":"https:\/\/www.liquidweb.com\/cloudsites\/","code":200}]

You can test with this URL: https://grandmascookieblog.com/cloud.php

Via curl I can see:

[ guzzle (track_redirect_codes)]$ curl -IL https://grandmascookieblog.com/cloud.php
HTTP/1.1 302 Found
Date: Thu, 12 Jan 2017 23:59:52 GMT
Server: Apache
Location: http://www.liquidweb.com/cloudsites/
Cache-Control: max-age=0
Expires: Thu, 12 Jan 2017 23:59:52 GMT
X-Cache: MISS from grandmascookieblog.com
Content-Type: text/html; charset=UTF-8

HTTP/1.1 301 Moved Permanently
Server: nginx/1.10.2
Date: Thu, 12 Jan 2017 23:59:53 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://www.liquidweb.com/cloudsites/
X-Frame-Options: SAMEORIGIN

HTTP/1.1 200 OK
Server: nginx/1.10.2
Date: Thu, 12 Jan 2017 23:59:53 GMT
Content-Type: text/html; charset=ISO-8859-1
Content-Length: 38913
Connection: keep-alive
Set-Cookie: production_www_sessid=1223adaee9e822dff41d9be79dd793a2; path=/
X-ua-compatible: IE=edge,chrome=1
X-Frame-Options: SAMEORIGIN

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hm, looking at the code again, it should be fine now.

Comment thread docs/request-options.rst Outdated
- track_redirects: (bool) When set to ``true``, each redirected URI encountered
will be tracked in the ``X-Guzzle-Redirect-History`` header in the order in
which the redirects were encountered.
- track_redirects: (bool) When set to ``true``, each redirected URI and Response
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

status code

Comment thread docs/request-options.rst Outdated
- track_redirects: (bool) When set to ``true``, each redirected URI and Response
Code encountered will be tracked in the ``X-Guzzle-Redirect-History`` and
``X-Guzzle-Redirect-Status-History`` headers respectively. All URIs and
Response Codes will be stored in the order in which the redirects were
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

status code

Comment thread docs/request-options.rst Outdated

Note: When tracking redirects the ``X-Guzzle-Redirect-History`` header will
exclude the initial request's URI and the ``X-Guzzle-Redirect-Status-History``
header will exclude the final response code.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

status code

Corrects some minor grammar issues.
Copy link
Copy Markdown
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

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

Can you please also check the status code-response code thing?

Comment thread docs/faq.rst Outdated
$redirectCodeHistory = $response->getHeader('X-Guzzle-Redirect-Status-History'); // retrieve Redirects HTTP Status history

// Add the initial URI requested to the (beginning of) URI history
array_unshift($reversedUriHistory, $initialRequest); // then we add the initial URL on the end
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is $reversedUriHistory correct here?

Comment thread docs/faq.rst
// (Optional) Combine the items of each array into a single result set
$fullRedirectReport = [];
foreach ($redirectUriHistory as $key => $value) {
$fullRedirectReport[$key] = ['location' => $value, 'code' => $redirectCodeHistory[$key]];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hm, looking at the code again, it should be fine now.

@sagikazarmark
Copy link
Copy Markdown
Member

@mallardduck I would like to release this in 6.3 in a few weeks. Can you check the remaining comments? Thanks

@sagikazarmark sagikazarmark modified the milestone: 6.3.0 Jan 13, 2017
@mallardduck
Copy link
Copy Markdown
Contributor Author

@sagikazarmark absolutely! I was hoping to get this done today at work however I ran out of time. I'll work on this over the weekend and shoot an updated PR your way.

I really appreciate the followup on this and wanted to let you know it's been awesome to collaborate and give back.

@sagikazarmark
Copy link
Copy Markdown
Member

@mallardduck thanks, I think this is ready. I changed some small wordings, also changed the FAQ example (removed some request options) to make it simpler. I think those weren't important for this feature anyway. If they were, please let me know, so we can put them back.

@sagikazarmark sagikazarmark merged commit 77a16c8 into guzzle:master Jan 15, 2017
thinsoldier pushed a commit to thinsoldier/guzzle that referenced this pull request Mar 2, 2017
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.

2 participants