Track redirect HTTP status codes#1711
Conversation
| $promise, | ||
| (string) $nextRequest->getUri() | ||
| (string) $nextRequest->getUri(), | ||
| (int) $response->getStatusCode() |
There was a problem hiding this comment.
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.
| $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); |
There was a problem hiding this comment.
Can you split this line to multiple ones?
|
Okay, you bought me. Can you please add some tests? |
|
Sure thing, I can totally add tests! |
...simple enough, this add the requested tests for the new redirect status code history header.
|
@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! |
| $promise, | ||
| (string) $nextRequest->getUri() | ||
| (string) $nextRequest->getUri(), | ||
| (string) $response->getStatusCode() |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Sorry about that, I guess I was a little confused initially. Totally get your point now tho.
Update PR incoming....
|
I have one last comment, apart from that good to go. |
|
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? |
|
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! |
|
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. |
sagikazarmark
left a comment
There was a problem hiding this comment.
Apart from a few wording comments, perfect 👍
| $client = new GuzzleHttp\Client(['expect' => false]); | ||
|
|
||
| How can I track a redirected requests HTTP codes? | ||
| ============================================ |
There was a problem hiding this comment.
Should be as long as the title
There was a problem hiding this comment.
Didn't realize that, I'll get that updated!
| How can I track a redirected requests HTTP codes? | ||
| ============================================ | ||
|
|
||
| You can enable the `track_redirects` option which will enable Guzzle to track |
There was a problem hiding this comment.
This first sentence with double "enabled" sounds a little bit weird...
There was a problem hiding this comment.
Maybe say "You can enable tracking the redirected URL and the status code via the ... option"
|
|
||
| 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 |
There was a problem hiding this comment.
Let's say status code instead of Response Code
| ``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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
This sounds good to me and seems to make it easier to read.
|
|
||
| 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 |
| $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 |
There was a problem hiding this comment.
How about using array_unshift instead?
There was a problem hiding this comment.
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)
| // (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]]; |
There was a problem hiding this comment.
What should be the first item here? IMO it should be the first URL if any, but currently it's the last.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Hm, looking at the code again, it should be fine now.
| - 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 |
| - 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 |
|
|
||
| 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. |
Corrects some minor grammar issues.
sagikazarmark
left a comment
There was a problem hiding this comment.
Can you please also check the status code-response code thing?
| $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 |
There was a problem hiding this comment.
Is $reversedUriHistory correct here?
| // (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]]; |
There was a problem hiding this comment.
Hm, looking at the code again, it should be fine now.
|
@mallardduck I would like to release this in 6.3 in a few weeks. Can you check the remaining comments? Thanks |
|
@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. |
|
@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. |
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