0

I've been working on an implementation of the PSR-7 UriInterface, and the specification regarding when an implementation should throw an InvalidArgumentException for some components is a little puzzling.

For example, UriInterface::withPath specifies throwing such an exception given an invalid path, but the very same docblock notes that, "Users can provide both encoded and decoded path characters," because, "Implementations ensure the correct encoding."

/**
 * ...
 *
 * Users can provide both encoded and decoded path characters.
 * Implementations ensure the correct encoding as outlined in getPath().
 *
 * @param string $path The path to use with the new instance.
 * @return static A new instance with the specified path.
 * @throws \InvalidArgumentException for invalid paths.
 */

That implementations are responsible for managing encoding is borne out throughout the rest of the specification.

Since implementations ensure the correct encoding, it would seem to follow that users of the implementation could pass any number of otherwise-invalid characters into a function like withPath, which would then be properly encoded rather than triggering an exception.

The only case I can think of that would warrant an InvalidArgumentException would be if withPath were passed a non-string (which, for whatever it's worth, seems to be Guzzle's interpretation of the specification).

A truly strict reading of PHP's brief introduction of InvalidArgumentException would seem to obviate this sort of "strict typing" interpretation, but I can't help but wondering if PHP-FIG had any thing else in mind, especially given the complexities of the URI syntax in general.

Are there any scenarios in which a UriInterface method such as withPath should throw an exception if it's passed a string?

Derek
  • 827
  • 11
  • 23

1 Answers1

1

I know, your question is a bit old :-)

Your assumptions are completely right!

About the part:

Users can provide both encoded and decoded path characters.
Implementations ensure the correct encoding as outlined in getPath().

This has nothing to do with the "invalid paths" (described in @throws tag). It just states - as you rightfully asserted, that users can provide both encoded and decoded characters, which are to be properly - in the sense of correspondingly - percent-encoded. E.g. some not encoded characters will be percent-encoded, and other ones not. In principle, the encoding scheme would be:

Percent-encode all URI path characters, except:

 - the unreserved characters,
 - the reserved characters of the subset "gen-delims",
 - the reserved characters of the subset "sub-delims",
 - the already percent-encoded characters.

On the other hand, an exception - InvalidArgumentException - is thrown in the following parameters' invalidity situations:

  • withScheme: is not a string and is not part of the list of allowed schemes;
  • withHost: is not a string;
  • withPort: is not numeric (or integer?) and is not in range [1, 65535];
  • withPath: is not a string;
  • withQuery: is not a string;
  • withFragment: is not a string;

And at last, a special treatment receives the URI string ($uri) passed as (optional NULL) constructor argument:

  • is not set
  • is not a string
  • is empty

... and the URI parts array, as the result of calling the parse_url on the URI string parameter (here throw UnexpectedValueException):

$uriParts = parse_url($uri);

if ($uriParts === FALSE) {
    throw new \UnexpectedValueException('URI could not be parsed!');
}

Note that I've listed all exception throwing situations inside the UriInterface implementation.