22
33namespace Aternos \CurlPsr \Psr18 \UriResolver ;
44
5+ use Aternos \CurlPsr \Exception \UriResolutionException ;
6+ use Aternos \CurlPsr \Psr7 \Uri ;
7+ use InvalidArgumentException ;
58use Psr \Http \Message \UriFactoryInterface ;
69use Psr \Http \Message \UriInterface ;
10+ use Throwable ;
711
812class UriResolver implements UriResolverInterface
913{
@@ -21,83 +25,25 @@ public function __construct(
2125 */
2226 public function resolve (UriInterface $ baseUri , UriInterface $ relativeUri ): UriInterface
2327 {
24- if ($ relativeUri ->getScheme () !== "" ) {
25- return $ relativeUri ;
26- }
27-
28- if ($ relativeUri ->getAuthority () !== "" ) {
29- return $ relativeUri
30- ->withPath ($ this ->removeDotSegments ($ relativeUri ->getPath ()))
31- ->withScheme ($ baseUri ->getScheme ());
32- }
33-
34- $ result = $ this ->uriFactory ->createUri ();
35- if ($ relativeUri ->getPath () === "" ) {
36- $ result = $ result ->withPath ($ baseUri ->getPath ());
37- if ($ relativeUri ->getQuery () !== "" ) {
38- $ result = $ result ->withQuery ($ relativeUri ->getQuery ());
39- } else {
40- $ result = $ result ->withQuery ($ baseUri ->getQuery ());
41- }
28+ if ($ baseUri instanceof Uri) {
29+ $ builtInBaseUri = $ baseUri ->getUri ();
4230 } else {
43- $ path = $ this ->mergePaths ($ baseUri ->getPath (), $ relativeUri ->getPath ());
44- $ result = $ result ->withPath ($ this ->removeDotSegments ($ path ))
45- ->withQuery ($ relativeUri ->getQuery ());
46- }
47- $ result = $ result ->withUserInfo ($ baseUri ->getUserInfo ())
48- ->withHost ($ baseUri ->getHost ())
49- ->withPort ($ baseUri ->getPort ());
50-
51- return $ result ->withScheme ($ baseUri ->getScheme ())
52- ->withFragment ($ relativeUri ->getFragment ());
53- }
54-
55- /**
56- * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.3
57- * @param string $base
58- * @param string $relative
59- * @return string
60- */
61- protected function mergePaths (string $ base , string $ relative ): string
62- {
63- if (str_starts_with ($ relative , "/ " )) {
64- return $ relative ;
65- }
66-
67- $ index = strrpos ($ base , "/ " );
68- if ($ index === false ) {
69- return "/ " . $ relative ;
70- }
71-
72- return substr ($ base , 0 , $ index + 1 ) . $ relative ;
73- }
74-
75- /**
76- * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
77- * @param string $path
78- * @return string
79- */
80- protected function removeDotSegments (string $ path ): string
81- {
82- $ resultParts = [];
83- $ parts = explode ("/ " , $ path );
84-
85- foreach ($ parts as $ part ) {
86- if ($ part === ".. " ) {
87- array_pop ($ resultParts );
88- } elseif ($ part !== ". " ) {
89- $ resultParts [] = $ part ;
31+ $ builtInBaseUri = \Uri \Rfc3986 \Uri::parse ((string )$ baseUri );
32+ if ($ builtInBaseUri === null ) {
33+ throw new UriResolutionException ($ baseUri , $ relativeUri , "Could not create built-in URI from base URI " );
9034 }
9135 }
9236
93- $ result = implode ("/ " , $ resultParts );
94-
95- if (str_starts_with ($ path , "/ " ) && !str_starts_with ($ result , "/ " )) {
96- $ result = "/ " . $ result ;
97- } else if ($ result !== "" && in_array (end ($ parts ), [". " , ".. " ])) {
98- $ result .= "/ " ;
37+ try {
38+ $ resolved = $ builtInBaseUri ->resolve ((string )$ relativeUri );
39+ } catch (Throwable $ e ) {
40+ throw new UriResolutionException ($ baseUri , $ relativeUri , "Could not resolve URI relative to base URI " , previous: $ e );
9941 }
10042
101- return $ result ;
43+ try {
44+ return $ this ->uriFactory ->createUri ($ resolved ->toString ());
45+ } catch (InvalidArgumentException $ e ) {
46+ throw new UriResolutionException ($ baseUri , $ relativeUri , "Could not create URI from resolved URI string " , previous: $ e );
47+ }
10248 }
10349}
0 commit comments