Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[HttpClient] Concerns about ResponseInterface::toArray() #31913

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
ubermuda opened this issue Jun 6, 2019 · 2 comments
Closed

[HttpClient] Concerns about ResponseInterface::toArray() #31913

ubermuda opened this issue Jun 6, 2019 · 2 comments

Comments

@ubermuda
Copy link

ubermuda commented Jun 6, 2019

First, I'm not sure what the design goal behind this component is, and I acknowledge that I did not take part in any prior discussions so I apologize in advance if I raise some concerns that have already be discussed.

That being said, I would argue that the goal of any HTTP client implementation that is called "HTTP Client" (and not, for example, "JsonAwareHttpClient") is to implement the protocol and stick to it so that people using it can leverage their knowledge of HTTP. It was also, if I am not mistaken, one of the main goals of Symfony 2.0.

In this optic, I would start by stating that HTTP has no concept of what an array is (it is clearly expressed in https://tools.ietf.org/html/rfc7230#section-3.3). By introducing the notion of an array in the interfaces of this component, we clearly deviate from the HTTP spec, which is in itself a red flag for me.

It's not only a matter of being "pure", it is also a matter of not misleading people. Symfony is a reference of good design and architecture in the PHP community, and with good reason. I often see junior developers take for granted what they can find in Symfony. It's often "not a bad thing" because the components have been so thoroughly designed, but in this particular case, it would be a problem to have people think that HTTP can transport "arrays" or any sort of structured data, when in fact it can not. I see this as a first step toward a design philosophy which I think does not match what Symfony ought to be (of course, I acknowledge that the framework philosophy is decided by the core team, I am merely giving my opinion here).

Apart from these considerations, I also think the current design has one huge technical flaw: from a library point of view, if I type-hint on HttpClientInterface, the behavior of ResponseInterface->toArray() is not defined.

The builtin implementation is hardcoded to work with JSON data, but there is nothing telling me this (or whatever format is supported) when what I get is an already instanciated object, and there is no standard exception for a format that is not supported. Last but not least, the JsonException implements the TransportExceptionInterface, which do not make much sense. It is not a transport problem, it is a decoding problem.

If the team is confident that the toArray method should indeed continue to exist, I would consider at least creating a DecodingException or something that would be the base exception for all decoding related problem. This way the developer can catch this and act accordingly. This exception should expose a way to know what exactly went wrong (format not supported, error while decoding, etc).

The ideal scenario for me would be to move this decoding business out of the HTTP Client. It could be for example included in the mime component, or just in a sub-namespace of the HTTP Client. Another possibility could be to offer specialized interfaces like JsonAwareHttpClient on which you could type hint and be absolutely sure what exact format is supported by the client.

Best regards,

@ro0NL
Copy link
Contributor

ro0NL commented Jun 8, 2019

see #30499 (comment) for some more info

In this optic, I would start by stating that HTTP has no concept of what an array is (it is clearly expressed in https://tools.ietf.org/html/rfc7230#section-3.3).

But PHP has, so this covers HTTP content to PHP array conversion. If supported / technically possible.

the behavior of ResponseInterface->toArray() is not defined

It more or less is;

* Gets the response body decoded as array, typically from a JSON payload.

@nicolas-grekas
Copy link
Member

Thanks for raising the point. For reference, toArray() has been introduced in #30499, following #30413 which introduced the component without it. Some general design principles have also been discussed in #30452.

Before the feature was added, e.g. this comment highlighted that the method was missing:

No help solving the pain of current HTTP clients when we need to do json_decode($response->getContents()) all over the applications

This method is the answer to this need. It could have been implemented in a helper class, but a core design goal of the work done here was to ship with an abstraction, so that one could get contractual behaviors with type declarations. Making a separate interface just for this would't have solved the "pain" that was mentionned in the comment.

That's for the "why" this method exists. To enter the abstraction, the method had to be defined in a generic enough way. This is what the description linked by @ro0NL above achieves. So yes, its behavior is well defined: it returns an array representation of the response body when its content-type is compatible with this representation. HTTP does know about content-types, so this fits the abstraction. When this representation cannot be created, an exception is thrown.

I would consider at least creating a DecodingException or something that would be the base exception for all decoding related problem

I agree with this statement, we're currrently missing this type of exception. Thanks for catching.

About the general design principles you mention: since we're not writting a religious book, we need technical arguments to decide if the method should enter the abstraction or not. The single technical pivot that software design gives us is the cost to change. How much changes needs an existing piece of code to implement new requirements? The only purpose of software design is to make this as cheap as possible, despicte the fact that future requirements are by defintion unknown. So, what's the added cost of toArray() in this regard? What's the kind of changes that using toArray() would incur? I've been thinking to this question a lot but can't find any that is specific to using the method itself. Well, I can think of only one: maybe in the future no commonly used content-types will be representable as arrays anymore, so that the method would become useless. But on the time scale we work on, this is unrealistic.

Given the benefits mentionned above, and the fact that it has not costs in terms of design, the decision was clear: it's a net win to have it.

@fabpot fabpot closed this as completed Jun 17, 2019
fabpot added a commit that referenced this issue Jun 17, 2019
…() fails because of content-type error (nicolas-grekas)

This PR was merged into the 4.3 branch.

Discussion
----------

[HttpClient] throw DecodingExceptionInterface when toArray() fails because of content-type error

| Q             | A
| ------------- | ---
| Branch?       | 4.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #31913
| License       | MIT
| Doc PR        | -

As spotted in the linked issue, we are missing this type of exception. It's a bug at the contracts level.

Commits
-------

3f16741 [HttpClient] throw DecodingExceptionInterface when toArray() fails because of content-type error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants