guzzle / uri-template

MIT License
145 stars 8 forks source link

pct-encoded reserved character(%2F) was encoded twice #18

Open TheNorthMemory opened 2 years ago

TheNorthMemory commented 2 years ago

PHP version: 8.1.3

Description

As of a community reporting, while the uri was already contains the pct-encoded(reserved characters) component, eg: AIO%2FFR. The {+var} syntax is explained this one as of AIO%252FFR. It is leading to misinterpreting the original percent data octet string.

I've also checked the RFC3986 and RFC6570 specifications.

RFC3986 2.4. When to Encode or Decode was mentioned there:

Because the percent ("%") character serves as the indicator for percent-encoded octets, it must be percent-encoded as "%25" for that octet to be used as data within a URI. Implementations must not percent-encode or decode the same string more than once, as decoding an already decoded string might lead to misinterpreting a percent data octet as the beginning of a percent-encoding, or vice versa in the case of percent-encoding an already percent-encoded string.

RFC6570 3.2.1. Variable Expansion was mentioned there:

The allowed set for a given expansion depends on the expression type: reserved ("+") and fragment ("#") expansions allow the set of characters in the union of ( unreserved / reserved / pct-encoded ) to be passed through without pct-encoding, whereas all other expression types allow only unreserved characters to be passed through without pct-encoding. Note that the percent character ("%") is only allowed as part of a pct-encoded triplet and only for reserved/fragment expansion: in all other cases, a value character of "%" MUST be pct- encoded as "%25" by variable expansion.

The pct-encoded reserved character(%2F) may pass through but it was encoded the char(%) to %25. It is mismatched the specs.

How to reproduce

<?php

require_once './vendor/autoload.php';

use GuzzleHttp\UriTemplate\UriTemplate;
echo UriTemplate::expand('merchant-service/images/{+slot}', ['slot' => 'AIO%2FFR']);
// result: merchant-service/images/AIO%252FFR
// Actually, there was required the url like this: `merchant-service/images/AIO%2FFR`

Possible Solution

Additional context

GrahamCampbell commented 1 year ago

Thanks for the report.

GrahamCampbell commented 1 year ago

Related: https://github.com/uri-templates/uritemplate-test/pull/41.

TheNorthMemory commented 1 year ago

Related: uri-templates/uritemplate-test#41.

Copy that. I've also strange that the RFC6570 wasn't any samples about double pct-encode.

It sugguest that this library should be followed the RFC3986 Implementations must not percent-encode or decode the same string more than once. If upgrading with this suggestion, it may works well with Guzzle\Psr7\Uri::filterPath (https://github.com/guzzle/psr7/blob/2.5/src/Uri.php#L693-L697)

GrahamCampbell commented 1 year ago

If you have any time to prepare a PR, or half of a PR, that would be much appreciated. I am spread thin these days, lol.