Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Uri Util Laravel Package

spomky-labs/uri-util

A lightweight PHP utility for parsing, normalizing, and manipulating URIs and URI references according to RFC 3986. It helps resolve relative paths, inspect components, and build reliable URL handling in frameworks and libraries without heavy dependencies.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a bare PHP library — no service provider, no facade, no config file. Install it and read the source; the surface area is small enough to audit in one sitting.

composer require spomky-labs/uri-util

Then look first at:

  1. vendor/spomky-labs/uri-util/composer.json — check the PHP constraint and whether it pulls psr/http-message or guzzlehttp/psr7. This determines whether you can hand its objects to Guzzle/Http::withOptions.
  2. vendor/spomky-labs/uri-util/src/ — the README is thin; the classes (Uri, Path, and query-string helpers) are the documentation. Note the exact namespace (SpomkyLabs\UriUtil\…) and whether methods are static helpers or immutable value objects.
  3. Existing tests in the repo — RFC 3986 examples there are the best spec for behavior.

First use case: canonicalize external URLs before you store, compare, or sign them. A typical Laravel entry point is a redirect/callback controller that receives a user-supplied redirect_uri or a signed storage URL and needs a stable, comparable form:

use SpomkyLabs\UriUtil\Uri;

$normalized = (string) Uri::fromString($request->query('redirect_uri'))
    ->withScheme(strtolower(...))  // adapt to actual API
    ->withFragment('');

Start with one narrow job — normalize a URL, or join path segments — and put it behind your own service class so you can swap it later.

Implementation Patterns

Canonical redirects in middleware. Normalize before deciding whether to redirect. Strip default ports, lowercase the host, collapse dot segments, drop the fragment. Return 301 only when the normalized form differs from the request URI.

Signing and webhook verification. Both sides must canonicalize identically. Build the string-to-sign from the normalized URI (path + sorted query, encoded exactly once, no fragment) so a client using ?a=1&b=2 and a server logging ?b=2&a=1 agree.

class CanonicalUri
{
    public function __construct(private string $raw) {}

    public function __toString(): string
    {
        $uri = Uri::fromString($this->raw);
        // strip fragment, normalize path, re-encode query
        return (string) $uri;
    }
}

Building URLs from config. Use the path helpers to join segments instead of rtrim($base, '/').'/'.ltrim($path, '/'):

$endpoint = Path::join(config('services.api.base'), 'v1', 'users', (string) $id);

This avoids double slashes and handles empty segments more predictably than string concatenation.

Deduplication and cache keys. Hash the normalized URI rather than the raw string. Two rows pointing at the same resource with different casing or trailing slashes collapse to one key.

Same-origin checks. Parse both URIs and compare scheme + host + port. Do not string-compare; https://example.com and https://example.com:443 are the same origin.

Adapter for future migration. Wrap every call in one small class (App\Support\UriNormalizer) with normalize(string): string and join(string ...$segments): string. When you move to league/uri, only that class changes.

Don't use it for route generation. Laravel's route() and url() already produce app URLs correctly. Reach for this package only for opaque/external URLs that Laravel doesn't own.

Testing pattern. Feed the RFC 3986 reference examples through both your code and the expected normalized output in a data provider; this catches encoding regressions fast.

Gotchas and Tips

  • Immutability is easy to forget. If withPath()/withQuery() return new instances (likely, given the PSR-7 influence), $uri->withPath('/x'); silently does nothing. Always reassign: $uri = $uri->withPath('/x');.
  • Encoding is the main source of bugs. Watch for %2F in path segments being decoded into a real slash, spaces becoming + in queries but %20 in paths, and double-encoding when you pass an already-encoded string back in. Normalize once, at the boundary.
  • No IDN / punycode handling. Unicode hostnames won't be converted to xn-- form. Do that explicitly if you accept international domains.
  • Fragments must not be signed or sent server-side. Strip #… before HMACs and before persisting as a redirect target unless you truly need it.
  • Query parsing edge cases. Repeated keys (a=1&a=2), bracket arrays (a[b]=c), and valueless keys (?flag) are where hand-rolled parsers break. Don't assume parse_str semantics match.
  • No relative-URI resolution. Resolving ../foo against a base URL is not a core feature; implement it yourself or move to league/uri.
  • PSR-7 interop is not automatic. If this class doesn't implement Psr\Http\Message\UriInterface, convert via (string) and GuzzleHttp\Psr7\UriResolver before handing it to Guzzle or Laravel's HTTP client.
  • Maintenance risk. Zero dependents and a score of zero is a signal: pin the version in composer.json, keep the adapter boundary, and plan an exit to league/uri for anything security-adjacent (signing, redirect validation).
  • Debugging tip. When a comparison fails, dump bin2hex((string) $uri) for both sides — invisible percent-encoding or trailing-slash differences show up immediately.
  • Extension point. The only real customization is your own wrapper; don't subclass the library's value objects, since internals may be final or change without notice.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin