{"id":29637245,"url":"https://github.com/illuminatech/url-trailing-slash","last_synced_at":"2025-07-21T18:02:11.575Z","repository":{"id":54599541,"uuid":"195264686","full_name":"illuminatech/url-trailing-slash","owner":"illuminatech","description":"Allows enforcing URL routes with or without trailing slash","archived":false,"fork":false,"pushed_at":"2025-03-06T15:40:24.000Z","size":66,"stargazers_count":47,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-10T16:17:53.681Z","etag":null,"topics":["laravel","route","routing","slash","trailing","url"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/illuminatech.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["klimov-paul"],"patreon":"klimov_paul"}},"created_at":"2019-07-04T15:22:02.000Z","updated_at":"2025-05-28T09:27:16.000Z","dependencies_parsed_at":"2024-03-25T11:57:28.955Z","dependency_job_id":"01dfd47b-e538-4ec8-90e6-4ce3e4eccbfc","html_url":"https://github.com/illuminatech/url-trailing-slash","commit_stats":{"total_commits":41,"total_committers":1,"mean_commits":41.0,"dds":0.0,"last_synced_commit":"46e2184b26871af63ccc5b0ada34fea98ae63d6a"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/illuminatech/url-trailing-slash","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Furl-trailing-slash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Furl-trailing-slash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Furl-trailing-slash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Furl-trailing-slash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/illuminatech","download_url":"https://codeload.github.com/illuminatech/url-trailing-slash/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Furl-trailing-slash/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266197369,"owners_count":23891286,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel","route","routing","slash","trailing","url"],"created_at":"2025-07-21T18:01:29.683Z","updated_at":"2025-07-21T18:02:11.559Z","avatar_url":"https://github.com/illuminatech.png","language":"PHP","funding_links":["https://github.com/sponsors/klimov-paul","https://patreon.com/klimov_paul"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/illuminatech\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://avatars1.githubusercontent.com/u/47185924\" height=\"100px\"\u003e\n    \u003c/a\u003e\n    \u003ch1 align=\"center\"\u003eLaravel URL Route Trailing Slash\u003c/h1\u003e\n    \u003cbr\u003e\n\u003c/p\u003e\n\nThis extension allows enforcing URL routes with or without trailing slash.\n\nFor license information check the [LICENSE](LICENSE.md)-file.\n\n[![Latest Stable Version](https://img.shields.io/packagist/v/illuminatech/url-trailing-slash.svg)](https://packagist.org/packages/illuminatech/url-trailing-slash)\n[![Total Downloads](https://img.shields.io/packagist/dt/illuminatech/url-trailing-slash.svg)](https://packagist.org/packages/illuminatech/url-trailing-slash)\n[![Build Status](https://github.com/illuminatech/url-trailing-slash/workflows/build/badge.svg)](https://github.com/illuminatech/url-trailing-slash/actions)\n\n\nInstallation\n------------\n\nThe preferred way to install this extension is through [composer](http://getcomposer.org/download/).\n\nEither run\n\n```\nphp composer.phar require --prefer-dist illuminatech/url-trailing-slash\n```\n\nor add\n\n```json\n\"illuminatech/url-trailing-slash\": \"*\"\n```\n\nto the require section of your composer.json.\n\nOnce package is installed you should manually register `\\Illuminatech\\UrlTrailingSlash\\RoutingServiceProvider` instance at your\napplication in the way it comes before kernel instantiation, e.g. at the application bootstrap stage. This can be done\nin 'bootstrap/app.php' file of regular Laravel application. For example:\n\n```php\n\u003c?php\n\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Foundation\\Configuration\\Exceptions;\nuse Illuminate\\Foundation\\Configuration\\Middleware;\n\n$app = Application::configure(basePath: dirname(__DIR__))\n    -\u003ewithRouting(\n        // ...\n    )\n    -\u003ewithMiddleware(function (Middleware $middleware) {\n        // ...\n    })\n    // ...\n    -\u003ecreate();\n\n$app-\u003eregister(new Illuminatech\\UrlTrailingSlash\\RoutingServiceProvider($app)); // register trailing slashes routing\n\nreturn $app;\n```\n\n\u003e Note: `\\Illuminatech\\UrlTrailingSlash\\RoutingServiceProvider` can not be registered in normal way or be automatically\n  discovered by Laravel, since it alters the router, which is bound to the HTTP kernel instance at constructor level.\n\nIn order to setup automatic redirection for the routes with trailing slash add `\\Illuminatech\\UrlTrailingSlash\\Middleware\\RedirectTrailingSlash`\nmiddleware to your HTTP kernel. For example:\n\n```php\n\u003c?php\n\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Foundation\\Configuration\\Exceptions;\nuse Illuminate\\Foundation\\Configuration\\Middleware;\n\n$app = Application::configure(basePath: dirname(__DIR__))\n    -\u003ewithRouting(\n        // ...\n    )\n    -\u003ewithMiddleware(function (Middleware $middleware) {\n        $middleware-\u003eprependToGroup('web', Illuminatech\\UrlTrailingSlash\\Middleware\\RedirectTrailingSlash::class); // enable automatic redirection on incorrect URL trailing slashes\n        // probably you do not need trailing slash redirection anywhere besides public web routes,\n        // thus there is no reason for addition its middleware to other groups, like API\n        // ...\n    })\n    // ...\n    -\u003ecreate();\n\n$app-\u003eregister(new Illuminatech\\UrlTrailingSlash\\RoutingServiceProvider($app)); // register trailing slashes routing\n\nreturn $app;\n```\n\n**Heads up!** Make sure you do not have any trailing slash redirection mechanism at the server configuration level, which\nmay conflict with `\\Illuminatech\\UrlTrailingSlash\\Middleware\\RedirectTrailingSlash`. Remember, that by default Laravel\napplication is shipped with `.htaccess` file, which contains redirection rule enforcing trailing slash absence in project URLs.\nMake sure you adjust or disable it, otherwise your application may end in infinite redirection loop.\n\n\nUsage\n-----\n\nThis extension allows enforcing URL routes with or without trailing slash. You can decide per each route, whether its URL\nshould have a trailing slash or not, simply adding or removing slash symbol ('/') in particular route definition.\n\nIn case URL for particular route is specified with the trailing slash - it will be enforced for this route, and request\nwithout slash in the URL ending will cause 301 redirection.\nIn case URL for particular route is specified without the trailing slash - its absence will be enforced for this route,\nand request containing slash in the URL end will cause 301 redirection.\n\nFor example:\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::get('items/', ItemController::class.'@index')-\u003ename('items.index'); // enforce trailing slash\nRoute::get('items/{item}', ItemController::class.'@show')-\u003ename('items.show'); // enforce no trailing slash\n\n// ...\n\necho route('items.index'); // outputs: 'http://example.com/items/'\necho route('items.show', [1]); // outputs: 'http://example.com/items/1'\n```\n\n\u003e Tip: the best SEO practice is having trailing slash at the URLs, which have nested pages, e.g. \"defines a folder\", and\n  have no trailing slashes at the URLs without nested pages, e.g. \"pathname of the file\".\n\nIn case you have setup `\\Illuminatech\\UrlTrailingSlash\\Middleware\\RedirectTrailingSlash` middleware, application will automatically\nredirect request with incorrect URL according to the routes definition. For the example above: request of `http://example.com/items`\ncauses redirect to `http://example.com/items/` while request to `http://example.com/items/1/` causes redirect to `http://example.com/items/1`.\n\n**Heads up!** Remember, that with this extension installed, you are controlling requirements of URL trailing slashes presence\nor absence in **each** route you define. While normally Laravel strips any trailing slashes from route URL automatically,\nthis extension gives them meaning. You should carefully examine your routes definitions, ensuring you do not set trailing\nslash for the wrong ones.\n\n\n### Slash in Root URL \u003cspan id=\"slash-in-root-url\"\u003e\u003c/span\u003e\n\nUnfortunally this extension is unable to handle trailing slashes for the project root URL, e.g. for a 'home' page.\nIn other words `\\Illuminatech\\UrlTrailingSlash\\Middleware\\RedirectTrailingSlash` middleware is unable to distinguish URL\nlike `http://examle.com` from `http://examle.com/`. This restriction caused by PHP itself, as `$_SERVER['REQUEST_URI']`\nvalue equals to '/' in both cases.\n\nYou'll have to deal with trailing slash for root URL separately at the server settings level.\n\n\n### Resource Routes \u003cspan id=\"resource-routes\"\u003e\u003c/span\u003e\n\nYou can define trailing slash presence for resource URLs using the same notation as for regular routes. In case resource\nname is specified with trailing slash, all its URLs will have it. For example:\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::resource('items/', ItemController::class); // enforce trailing slash\nRoute::resource('categories', CategoryController::class); // enforce no trailing slash\n\n// ...\n\necho route('items.index'); // outputs: 'http://example.com/items/'\necho route('items.show', [1]); // outputs: 'http://example.com/items/1/'\n\necho route('categories.index'); // outputs: 'http://example.com/categories'\necho route('categories.show', [1]); // outputs: 'http://example.com/categories/1'\n```\n\nYou can control trailing slash presence per each resource route using options 'trailingSlashOnly' and 'trailingSlashExcept' options.\nThese behave in similar to regular 'only' and 'except', specifying list of resource controller methods, which should\nor should not have a trailing slash in their URL. For example:\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::resource('items', ItemController::class, ['trailingSlashOnly' =\u003e 'index']); // trailing slash will be present only for 'index'\nRoute::resource('categories', CategoryController::class, ['trailingSlashExcept' =\u003e 'show']); // trailing slash will be present for all but 'show'\n\n// ...\n\necho route('items.index'); // outputs: 'http://example.com/items/'\necho route('items.show', [1]); // outputs: 'http://example.com/items/1'\n\necho route('categories.index'); // outputs: 'http://example.com/categories/'\necho route('categories.show', [1]); // outputs: 'http://example.com/categories/1'\n```\n\n\u003e Note: 'trailingSlashExcept' option takes precedence over 'trailingSlashOnly'.\n\n\n### Trailing Slash in Pagination \u003cspan id=\"trailing-slash-in-pagination\"\u003e\u003c/span\u003e\n\nUnfortunately, the trailing slash will not automatically appear at pagination URLs.\nThe problem is that Laravel paginators trim the trailing slashes from the URL path at the constructor level.\nThus even adjustment of `\\Illuminate\\Pagination\\Paginator::currentPathResolver()` can not fix the problem.\n\nIn case you need a pagination at the URL endpoint with a trailing slash, you should manually set the path for it, using\n`\\Illuminate\\Pagination\\AbstractPaginator::withPath()`. For example:\n\n```php\n\u003c?php\n\nuse App\\Models\\Item;\nuse Illuminate\\Support\\Facades\\URL;\n\n$items = Item::query()\n    -\u003epaginate()\n    -\u003ewithPath(URL::current());\n```\n\n\n### Trailing Slash in Unit Tests \u003cspan id=\"trailing-slash-in-unit-tests\"\u003e\u003c/span\u003e\n\nSince `Illuminatech\\UrlTrailingSlash\\RoutingServiceProvider` can not be registered as regular data provider, while writing\nunit and feature tests you will have to manually register it within test application before test kernel instantiation.\nThis can be done within your `\\Tests\\CreatesApplication` trait:\n\n```php\n\u003c?php\n\nnamespace Tests;\n\nuse Illuminate\\Contracts\\Console\\Kernel;\nuse Illuminatech\\UrlTrailingSlash\\RoutingServiceProvider;\n\ntrait CreatesApplication\n{\n    /**\n     * Creates the application.\n     *\n     * @return \\Illuminate\\Foundation\\Application\n     */\n    public function createApplication()\n    {\n        $app = require __DIR__.'/../bootstrap/app.php';\n\n        $app-\u003eregister(new RoutingServiceProvider($app)); // register trailing slashes routing\n\n        $app-\u003emake(Kernel::class)-\u003ebootstrap();\n\n        return $app;\n    }\n}\n```\n\nHowever, this in not enough to make tests running correctly, because Laravel automatically strips trailing slashes from requests\nURL before staring test HTTP request. Thus you will need to override `\\Illuminate\\Foundation\\Testing\\Concerns\\MakesHttpRequests::prepareUrlForRequest()`\nin the way it respects trailing slashes. This can be achieved using `Illuminatech\\UrlTrailingSlash\\Testing\\AllowsUrlTrailingSlash` trait.\nFor example:\n\n```php\n\u003c?php\n\nnamespace Tests;\n\nuse Illuminate\\Foundation\\Testing\\TestCase as BaseTestCase;\nuse Illuminatech\\UrlTrailingSlash\\Testing\\AllowsUrlTrailingSlash;\n\nabstract class TestCase extends BaseTestCase\n{\n    use CreatesApplication;\n    use AllowsUrlTrailingSlash;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filluminatech%2Furl-trailing-slash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filluminatech%2Furl-trailing-slash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filluminatech%2Furl-trailing-slash/lists"}