The progress of HTTP client

377 views
Skip to first unread message

Tobias Nyholm

unread,
Dec 4, 2017, 4:45:07 AM12/4/17
to PHP Framework Interoperability Group

After some time of carefully reviewing and discussions on Github I want to let the mailing list know that we are soon comfortable with how PSR-18 looks. We have documented the discussions in the meta document (https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/http-client-meta.md)

 

I invite you all to review the PSR and give some feedback. You will find the current specification here: https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/http-client.md


Regards

Tobias Nyholm

Woody Gilk

unread,
Dec 4, 2017, 8:44:41 AM12/4/17
to PHP Framework Interoperability Group
A couple of notes:

public function sendRequest($request)

Could this be made shorter, without losing meaning?

public function send($request)

Regarding the exception interfaces:

interface ClientException extends \Throwable

Why Throwable instead of Exception or RuntimeException?

Everything else looks very straight forward!

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/35361389-c53a-4ee4-ac79-195402d9ab14%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tobias Nyholm

unread,
Dec 5, 2017, 5:03:09 PM12/5/17
to PHP Framework Interoperability Group
Thank you for the review. 

Using `send` would make us incompatible with Guzzle and Buzz. It would force php-http's clients to have two methods doing the same thing. So we are more pragmatic here by using `sendRequest`. 

About `\Throwable`... Im not sure. I will do some research and make a PR to the specs. 
Thanks!


Den måndag 4 december 2017 kl. 14:44:41 UTC+1 skrev Woody Gilk:
A couple of notes:

public function sendRequest($request)

Could this be made shorter, without losing meaning?

public function send($request)

Regarding the exception interfaces:

interface ClientException extends \Throwable

Why Throwable instead of Exception or RuntimeException?

Everything else looks very straight forward!
On Mon, Dec 4, 2017 at 3:45 AM, Tobias Nyholm <tobias...@gmail.com> wrote:

After some time of carefully reviewing and discussions on Github I want to let the mailing list know that we are soon comfortable with how PSR-18 looks. We have documented the discussions in the meta document (https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/http-client-meta.md)

 

I invite you all to review the PSR and give some feedback. You will find the current specification here: https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/http-client.md


Regards

Tobias Nyholm

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

Sara Golemon

unread,
Dec 5, 2017, 9:17:50 PM12/5/17
to PHP Framework Interoperability Group
On Monday, December 4, 2017 at 8:44:41 AM UTC-5, Woody Gilk wrote:
A couple of notes:

public function sendRequest($request)

Could this be made shorter, without losing meaning?

public function send($request)

IMO interfaces should have more-expressive names to avoid colliding with local methods in a given class.
 
Regarding the exception interfaces:

interface ClientException extends \Throwable

Why Throwable instead of Exception or RuntimeException?

For one: \Exception is a concrete class, \Throwable is an interface.  An interface can't extend a concrete class.

In this form, an implementation can easily extend \Exception in the process of implementing ClientException (if it chooses to).

class MyAwesomeHttpClientEcception extends \Exception implements ClientException {...}

-Sara

Larry Garfield

unread,
Dec 5, 2017, 9:46:21 PM12/5/17
to php...@googlegroups.com
Hm. Prior specs just defined an exception interface on its own, and said
"y'all need to implement this in addition to extending whatever exception"[1]
[2][3].

Of course, those specs were all PHP 5-compatible so Throwable wasn't a thing.
If we continue that pattern in the future then making those exception
interfaces extend Throwable makes a lot of sense, as it syntactically calls
out what they're for while still giving implementers the ability to extend
whatever base exception is most logical.

I kind of like that.

--Larry Garfield

[1] http://www.php-fig.org/psr/psr-6/#cacheexception
[2] http://www.php-fig.org/psr/psr-11/#32-psrcontainercontainerexceptioninterface
[3] http://www.php-fig.org/psr/psr-16/#22-cacheexception
signature.asc

Niklas Keller

unread,
Dec 8, 2017, 7:19:48 AM12/8/17
to PHP Framework Interoperability Group
I have just reviewed the current document, you can find my feedback below.

Client: It specifies that a client that decodes a gzipped body must remove the corresponding header. Does it also have to remove a chunked encoding header? It's a requirement of the HTTP specification that a client decodes chunked encoding.

Exceptions: Smaller issues, like wrong HTTP versions, must not result in an exception being thrown. This seems problematic to me. First of all, there's no definition of "smaller issues". Next, I'd not classify a wrong HTTP version as smaller issue. The semantics might change with newer HTTP versions and a client that doesn't understand these shouldn't just send a request with a newer HTTP version.

Another point is the missing mention of 1XX responses here, as they can be parsed into a valid HTTP response, but they're actually intermediate responses.

RequestException + NetworkException: getRequest() is documented to return a request that might be different from the original request. Does it make sense to add another method that returns the original request?

Tobias Nyholm

unread,
Dec 9, 2017, 3:43:43 AM12/9/17
to PHP Framework Interoperability Group
Thank you. 

Client:
You are just referring to an example that show that if you modify the body you must to the same modifications on the headers. 

Exceptions:
By "smaller issues" we mean: Things that do not stop you form sending a request. If you are using the wrong HTTP version in the status line, that does not stop the client from sending the request. The server may be able to handle that anyways. So the client should not be "smart" and help you to fail early. 

We do mention 1xx responses. They should be handled by the client. 

RequestException
Hm, I do not think so. Why would you ever be interested in a Request that was not sent? Im way more interested in the request that failed, right?

//Tobias

Niklas Keller

unread,
Dec 9, 2017, 8:00:18 AM12/9/17
to PHP Framework Interoperability Group
Client:
You are just referring to an example that show that if you modify the body you must to the same modifications on the headers. 

Yes, I guess that's rather a specific question, as it should be clear to other modifications. Should the `transfer-encoding: chunked` header be removed by a client or not?
 
Exceptions:
By "smaller issues" we mean: Things that do not stop you form sending a request. If you are using the wrong HTTP version in the status line, that does not stop the client from sending the request. The server may be able to handle that anyways. So the client should not be "smart" and help you to fail early. 

A wrong HTTP version isn't a small issue to me. Different HTTP versions have a different message syntax and it's not wise just sending a wrong HTTP version the client doesn't understand. The list of possible HTTP versions is quite small, I think explicitly checking the version makes sense in every client. In the worst case, sending another HTTP version the client doesn't understand might result in a security vulnerability, because the client interprets things the wrong way.
 
We do mention 1xx responses. They should be handled by the client.

Yes, they're mentioned in the interface docs, but not in the specification itself.
 
RequestException
Hm, I do not think so. Why would you ever be interested in a Request that was not sent? Im way more interested in the request that failed, right?

I don't have an immediate use case, but I can imagine that it could be useful if you want to find the failed request within a set of requests. Having the original request available would allow using ===, which explicitly isn't possible with the current interface.

On the other hand, the request will usually be available at the place the exception is caught I guess.
Message has been deleted

Barry vd. Heuvel

unread,
Feb 14, 2018, 7:00:25 AM2/14/18
to PHP Framework Interoperability Group
Hello Tobias,

Seeing as in the last two months, no new issues have arised, except for this PR discussing the formatting/necessity of a paragraph; https://github.com/php-fig/fig-standards/pull/980, is it possible to move this to review? 

If there are no big objections and you are happy with the current document, a vote can be opened to move this to Review, right?

Thank you for your work so far! No intention to rush this, but it seems to stall a bit recently, while overall looks very useful :)

Op zaterdag 9 december 2017 14:00:18 UTC+1 schreef Niklas Keller:

Barry vd. Heuvel

unread,
Feb 14, 2018, 7:11:46 AM2/14/18
to PHP Framework Interoperability Group
Apologies, I now see that PSR-18 is referenced in the Sunshine meetings (https://groups.google.com/forum/#!topic/php-fig/sjASl6ltjHI )

PSR - 18 HTTP Client (Abandoned)
  • Tobias identified an issue and will be notifying the group to source needed changes.
    • Tobias is waiting on Sara to offer feedback.
  • This PSR needs 2 implementations to move forward.
Status abandoned, is that supposed to be Draft? As you are discussing the issue with the group. Or are you in search of a new Editor?

Op woensdag 14 februari 2018 13:00:25 UTC+1 schreef Barry vd. Heuvel:

Tobias Nyholm

unread,
Feb 15, 2018, 2:47:09 AM2/15/18
to PHP Framework Interoperability Group
Yeah, it has stalled for a few weeks. but we are working on it again. The specification looks good, we are currently deciding on an upgrade path from HTTPlug. We have a proposal that we think will work. I've invited a few to have a look on it (Sara included). If this small group think it is fine I will publish it so every one could give their comments.

If no major issues are found I will move the PSR to review.

Stefano Torresi

unread,
Feb 18, 2018, 6:28:18 AM2/18/18
to php...@googlegroups.com
As far as I know, PSR-18 has never been marked as abandoned, I don't even think the requirements to do so have ever been satisfied. Could the secretaries confirm, please?

Alessandro Lai

unread,
Feb 19, 2018, 4:51:50 PM2/19/18
to PHP Framework Interoperability Group
As per our bylaws (see https://www.php-fig.org/bylaws/psr-workflow/#abandoned), abandonment must be explicitly declared either by an abandonment vote, or by a secretary, but with some prerequisites:

 - missing editor or sponsor for more than 60 days (not the case here)
 - no activity in 6 months (not the case either, see commits on draft: https://github.com/php-fig/fig-standards/commits/master/proposed/http-client)

So yes, PSR-18 is not abandoned but in draft stage, as correctly stated in our repo/site: https://www.php-fig.org/psr/#draft

Barry vd. Heuvel

unread,
Feb 25, 2018, 2:00:40 PM2/25/18
to PHP Framework Interoperability Group
Good to hear it was just a typo :)

> The specification looks good, we are currently deciding on an upgrade path from HTTPlug. We have a proposal that we think will work. 

Does that mean the interface is likely to remain the same?

I'm currently working on an upgrade for Omnipay from Guzzle to (hopefully) PSR-18 (current work in progress is also based on HTTplug), hence this PSR :)

Op maandag 19 februari 2018 22:51:50 UTC+1 schreef Alessandro Lai:
Message has been deleted

Luis Pabón

unread,
Mar 16, 2018, 12:24:07 PM3/16/18
to PHP Framework Interoperability Group
My 2p:

  • This PSR needs async, otherwise there's not much value on it - I'd recommend following closely what guzzle is already doing
  • sendRequest is redundant. public function send(RequestInterface $request): Response
  • Exceptions should be way more verbose: need BadRequestException, ConflictException, TimeoutException, UnauthorisedException etc to accurately error-handle without boilerplate (eg checking status code).
  • Exceptions must also give access to the response as well as the HTTP status code separately

Tobias Nyholm

unread,
Mar 16, 2018, 12:58:56 PM3/16/18
to PHP Framework Interoperability Group

Thank you Luis for the feedback. Here are some short answers:

* Regarding async: See the meta document: https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/http-client-meta.md
* Method signature: We want to make sure that major libraries could implement this interface without breaking BC.
* Regarding exceptions' verbosity: See the meta document
* Exceptions is thrown when there is no response. =)

See the meta document and the current specification. Most of your ideas has been visited already.

https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/http-client.md
Message has been deleted

Tobion

unread,
Apr 3, 2018, 8:23:04 AM4/3/18
to PHP Framework Interoperability Group
I've reviewed the current doc and there are two points I highly disagree with and that does not seem to fit common use-cases.

1. The spec says, implementation must not follow redirects. This means any user of those interfaces must re-implement redirections themselves? I don't see how this default behavior is the desired behavior for almost all use-cases.
The meta doc says "All clients communicating to an external API use some form of HTTP client.". But redirects are common in HTTP and APIs. So every package relying on these standard interfaces is basically broken and does not support redirects unless they handle them manually?

2. The spec says error responses do not result in exceptions. From my experience this is also very bad for most cases. Basically the only case where you don't care about the response code is if you write a proxy. Other than that you will need to check the response code for every response you get. What I've seen alot, is people doing stuff like `if ($response->getStatusCode() !== 200) handleError()`. But that does not work as soon as you receive a 201 for example. As you can see properly checking for error responses is not super straight forward. And PSR-7 does not define a method like `$response->isErrorCode`. So people either need to implement that themselves. Or rely on packages providing helper methods for things like that like guzzle/psr7. But then it undermines the goal of the PSR to avoid version conflicts and avoid concrete implementations.
If sendRequests throws exceptions for error responses, people do not need to implement checking for error respones at least as that is handled by the implementation. And in most cases the workflow for error respones is different than for success ones (retrying, logging, aborting etc.). So handling that with exceptions is more natural and logical to me.

Larry Garfield

unread,
Apr 3, 2018, 10:08:03 AM4/3/18
to php...@googlegroups.com
The problem with dumping all of the error handling and redirection logic into
the client itself is that it presumes what you want that error handling and
redirection logic to be.

If a response comes back with a 301 Moved Permanently, I may want to know that
so I can update my own records (eg, a URL is stored in a DB somewhere). If
the client automatically follows the redirect then I don't know to do so.

Similarly, an indexer script doesn't want a 404 to generate an exception. It
expects a large percentage of its responses to be 404s, and exceptions are
super expensive. It would want to simply record that a 404 happened and keep
on going.

In either case, the proper way to handle it is to have an HTTP client
implementation that does what the spec says and just pass back the response,
whatever it is, and then compose various error handling implementations around
it. So you could easily wrap a "just follow redirects and don't bother
telling me" object around the actual client, or a "turn 4xx responses into
exceptions" wrapper, etc. There's probably some generic ones that could be
built or just write one for your application (that auto-updates your URL
database for redirects, for instance).

The question then is how to word the spec such that such wrapper
implementations of the interface are not technically spec violating, even
though they're the correct approach.

--Larry Garfield
> > Thank you Luis for the feedback. Here are some short answers:
> >
> > * Regarding async: See the meta document:
> > https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/
> > http-client-meta.md * Method signature: We want to make sure that major
> > libraries could implement this interface without breaking BC.
> > * Regarding exceptions' verbosity: See the meta document
> > * Exceptions is thrown when there is no response. =)
> >
> > See the meta document and the current specification. Most of your ideas
> > has been visited already.
> >
> >
> > https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/
> > http-client.md>
> > Den fredag 16 mars 2018 kl. 17:24:07 UTC+1 skrev Luis Pabón:
> >> My 2p:
> >> - This PSR needs async, otherwise there's not much value on it - I'd
> >> recommend following closely what guzzle is already doing
> >> - sendRequest is redundant. public function send(RequestInterface
> >> $request): Response
> >> - Exceptions should be way more verbose: need BadRequestException,
> >> ConflictException, TimeoutException, UnauthorisedException etc to
> >> accurately error-handle without boilerplate (eg checking status code).
> >> - Exceptions must also give access to the response as well as the
> >>>>>>>> PSR - 18 HTTP Client (*Abandoned*)
> >>>>>>>>
> >>>>>>>> - Tobias identified an issue and will be notifying the group to
> >>>>>>>> source needed changes.
> >>>>>>>>
> >>>>>>>> - Tobias is waiting on *Sara to offer feedback*.
> >>>>>>>>
> >>>>>>>> - This PSR needs 2 implementations to move forward.
signature.asc
Reply all
Reply to author
Forward
0 new messages