Skip to content

Fix previousPath() returning full URL for external referrers (fixes laravel/framework#57456)#5

Open
JoshSalway wants to merge 2 commits into12.xfrom
fix/previous-path-external-referrer-12x
Open

Fix previousPath() returning full URL for external referrers (fixes laravel/framework#57456)#5
JoshSalway wants to merge 2 commits into12.xfrom
fix/previous-path-external-referrer-12x

Conversation

@JoshSalway
Copy link
Owner

@JoshSalway JoshSalway commented Mar 18, 2026

Summary

Fixes laravel#57456 -- previousPath() returns the full URL path from external referrers instead of just the path portion relative to the application. When a user arrives from https://google.com/search?q=laravel, previousPath() returns /search instead of / (no meaningful previous path within the app).

Root Cause

The bug exists because previousPath() uses string subtraction (str_replace($this->to('/'), '', ...)) to strip the application's base URL from the referrer URL. When the referrer is an external domain (e.g., https://google.com/search), str_replace finds no match and returns the full external path /search unchanged. The method assumes the referrer always comes from the same domain, which is incorrect for external referrers, bookmarks, and cross-origin links.

Additionally, the str_replace approach fails when the application is mounted at a sub-path (e.g., https://example.com/subdir/) because it performs a literal string replacement that can't properly handle base path stripping.

Why This Fix Works

This fix works because it uses parse_url($url, PHP_URL_PATH) to extract only the path component from the referrer URL, completely ignoring the domain and query string. For base path stripping, it uses parse_url($this->to('/'), PHP_URL_PATH) to get the application's base path and removes it with a regex anchor. This approach is domain-agnostic -- it correctly extracts the path regardless of whether the referrer is internal or external. External referrer paths are returned as-is, which is the correct behavior (the path is meaningful to the caller).

Alternatives Considered

We chose this approach over comparing domains and returning / for external referrers because: (1) the method's contract is to return a path, not to validate origin; (2) some applications legitimately use previousPath() to inspect where users came from, even external paths; (3) the parse_url approach is simpler, handles edge cases (missing paths, query strings, fragments) natively, and correctly handles sub-path deployments that the old str_replace approach broke.

Files Changed

  • src/Illuminate/Routing/UrlGenerator.php -- Rewrote previousPath() to use parse_url() instead of str_replace()
  • tests/Routing/RoutingUrlGeneratorTest.php -- Added tests for external referrers and sub-path deployments

JoshSalway and others added 2 commits March 19, 2026 04:39
Adds tests to verify previousPath() correctly extracts path component
when the referer header contains an external domain URL or when the
application is deployed in a subdirectory.

Refs laravel#57456

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
previousPath() used str_replace to strip the app URL from the referer,
which returned the full external URL when the referer came from a
different domain. Switch to parse_url() to extract the path component
directly, and strip the base path for subdirectory deployments.

Backport of laravel#59159 (13.x) to 12.x.

Fixes laravel#57456

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant