-
Notifications
You must be signed in to change notification settings - Fork 257
[1.x] Fix encoded URL #663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Please merge this, so I can avoid having to read hieroglyphs in my URL 🙏 |
Also facing this bug, becomes very annoying when dealing with dashboards where the URL has a lot of state. Please merge @reinink especially if 2.0 is dropping soon? Would save a lot of headache |
@RobertBoes Hey just to be clear, is the issue here simply that the query params are harder to read because they are encoded? Or is something broken? Just want to make sure I understand the issue. |
@reinink I'd say it's broken, not just hard to read. Sure, it doesn't have an impact on the server interpreting the URL, but it still leads to strange behavior. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, so I did some testing with this, and I don't think it's quite right yet. I think this encoding is actually important otherwise special characters can mess up your query params. For example, in my app I have a search feature. Before this change, searching for "jonathan&amy" works great and results in this URL:
Here I have a single query param — However, after this change I get this URL instead:
Which, as you know, means I now have two query params — This is broken as a result of this change, as putting a special character anywhere in your app that ends up in a query param (which is super common) will break someone's app. So I understand that with the current behavior visiting |
Hey @reinink Maybe I am not following exactly what you mean, but if I understand correctly...
This is expected behavior with the
Surely this is only the
Would result in: ['search' => 'jonathan$amy'] To me it sounds like your app relies on the encoding issues introduced in #592, which this PR tries to fix. If you're worried about breaking existing apps by merging this, I can understand that. However I also think it's a bad idea to call the "bug" a feature, if people do not want encoded URLs. Maybe provide a way to disable it, but leave it on by default? |
Chiming in another idea; Let the user provide the URL. So a default implementation that can be overwritten. For example, I don't care about the path prefix, so then I could easily just get the path+query as was done previously. That way I'd send the same URL to the frontend as what's visible in the browser |
I'd even be happy with an option within the Inertia config to specify what characters should be encoded, e.g. Then you've got more control and everyone wins |
I'd really like to avoid having to create a config option for something...it feels like something that should be solvable without one. @RobertBoes @heychazza what's your primary concern here? The fact that history state gets updated with the encoded query params? Or that they are encoded and now visually look worse? |
I still think this is the best solution! Currently it's quite cumbersome to overwrite the URL generation part. See #503 |
I totally get that, I wouldn't want that to be "yet another config option", or something like
|
Yeah agreed, I'm also using the Spatie Query Builder and it's very hard to understand the URL filters when it's all %20 everything. Would definitely love if we could just bind our own thing, as I do understand its very niche. |
I'm also waiting for merge. temporary solution <?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Inertia\Support\Header;
use Symfony\Component\HttpFoundation\Response;
class FixUrlEncodeInertiaPageRequest
{
/**
* @see https://github.com/inertiajs/inertia-laravel/pull/663
*
* Handle an incoming request.
*
* @param Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response|\Illuminate\Http\JsonResponse) $next
*/
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
if ($request->header(Header::INERTIA)) {
$response->original['url'] = rawurldecode($response->original['url']);
$response->setData($response->original);
}
return $response;
}
} add in service provider register method use App\Infrastructure\Illuminate\ResponseFactory as ServicesResponseFactory;
use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract;
use Illuminate\Contracts\View\Factory as ViewFactoryContract;
//register
$this->app->singleton(ResponseFactoryContract::class, function ($app) {
return new ServicesResponseFactory($app[ViewFactoryContract::class], $app['redirect']);
}); <?php
namespace App\Infrastructure\Illuminate;
use Illuminate\Routing\ResponseFactory as RoutingResponseFactory;
final class ResponseFactory extends RoutingResponseFactory
{
public function view($view, $data = [], $status = 200, array $headers = [])
{
if (isset($data['page']['url'])) {
$data['page']['url'] = rawurldecode($data['page']['url']);
}
return parent::view($view, $data, $status, $headers);
}
} |
i think query values should be encoded, but query keys should not, like this:
|
Hey @joetannenbaum Could you please take a look at this PR? |
…aracters This PR provides a more consistent approach to URL handling in Inertia responses by: - Adding support for preserving trailing slashes in URLs - Improving readability by decoding special characters in query parameters - Maintaining compatibility with proxy prefixes - Ensuring URL consistency for SEO and debugging Previously, characters like slashes (%2F) and ampersands (%26) were encoded in the URL, making debugging more difficult and causing inconsistencies between browser URLs and Inertia history state URLs. Comprehensive tests have been added for both trailing and non-trailing slash scenarios, as well as specific tests for slash and ampersand handling in query parameters. Resolves issues discussed in inertiajs#663
I agree with @patie that key shouldn't be encoded, but value could be. |
Vue-router has a parseQuery/stringifyQuery option, which are much more flexible than Inertia current Exemple: parseQuery(query) {
return require('qs').parse(query, {
comma: true,
});
},
stringifyQuery(query) {
const result = require('qs').stringify(query, {
encodeValuesOnly: true,
skipNulls: true,
arrayFormat: 'comma',
commaRoundTrip: true,
});
return result ? '?' + result : '';
}, |
I've played around with this issue to understand the challenges here. Here's what I think:
Honestly, I feel like going with encoded URLs is the way to go, but I understand the desire for clean URLs. I'm not committing to this yet, but maybe we could introduce a static Response::resolveUrlUsing(function ($request) {
$url = Str::start(Str::after($request->fullUrl(), $request->getSchemeAndHttpHost()), '/');
return str_replace(['%5B', '%5D'], ['[', ']'], $url);
}); |
@pascalbaljet Perhaps this PR wasn't the right solution, but the core issue still remains, and has been for a year now. Inertia sends back a different URL to the frontend then what was used to make the request in the first place. If you visit https://inertiajs.com/?string[]=nothing the page loads and Inertia pushes a new URL and changes it to the encoded variant. This causes all kinds of issues, it might even affect SEO as the URLs are different (so, duplicate content). Screen.Recording.2025-06-04.at.11.56.55.mov |
I agree that the URL pushing is unwanted and that we should look for a solution, but we can't use |
@pascalbaljet so will this be worked on, or? It's quite exhausting to have a PR that attempts to solve a problem closed, after a whole year, with no alternative solution currently in the works. |
I proposed two possible alternative solutions: the |
Yes, but are you going to open a PR with your proposed solution(s)? Presenting them in a now closed PR isn't going to do much. |
Sure, I've already mentioned that it takes some time to find the best solution. Sharing these ideas here is just a way to share what has crossed my mind so far. |
Just chiming in here, it's quite sad and worrying that @RobertBoes has found a big issue which could cause issues for sites heavy in SEO (like one I'm building), only for it to sit idle for a year and now suddenly gets closed by you @pascalbaljet without any alternative solution delivered. I appreciate we're all busy but I'd argue that Inertia.js is the biggest option in the Laravel ecosystem, especially given how popular the likes of Vue and React are, yet issues like this have stood still considering this package is maintained by a company with full-time employees. Personally this doesn't give me a lot of confidence using Inertia on anything other than a dashboard where SEO is less of a concern, I'm already part way through a venture of mine where SEO plays a huge part in it. At this point I wonder if I'm worth moving to something like Nuxt, or Next.js to be honest. Oh well, I guess its better I'd find out sooner than later.. |
I'm repeating myself, but we definitely want a solution for this, let me be clear about that :) It's a shame that some PRs/issues are opened for a long time. After a year, it might feel 'suddenly', but it's part of our goal to get the repos in great shape, and this PR was one of the first on my list. Since this PR is a breaking change, and even one that's going to cause more bugs, it has no chance of getting merged. That doesn't take the issue away; it just invalidates this proposed solution, and we're going to work on an alternative solution. |
Btw, there is still an open issue for this (#707) where we can discuss alternative solutions. |
What about the breaking change that was introduced here in the first place? I know you weren't around then, and I'm not blaming you or anything. As someone trying to contribute it just feels like contributions are unwanted. I can change a PR, I'm open to suggestions. But seeing how maintenance here is done, it's becoming quite ridiculous. Jess opens a PR, merges it herself within 2 days. The community doesn't even have time to test. That PR introduced a breaking change, it was mentioned, the team didn't care. The PR isn't reverted because of a breaking change. Community tries to address the issue, and it's just left in the dust. Now we're a year later, this PR has pretty much been idling for half a year, and it's suddenly closed, while one maintainer already mentioned it's a good solution. Yes, it has one side-effect, but that's a side-effect on top of something that already doesn't work properly. Feels a lot like having double standards, maintainers can freely introduce breaking changes, as long as it doesn't affect Laravel products, but external contributions are inspected very thoroughly and will simply be closed.
I already proposed that on October 3rd: #663 (comment) / #663 (comment)
I'm sorry, but this has already happened once: Close all issues and PRs in hopes people don't take the effort to invest time to recreate the issue / PR. |
The one opened in January with two proposed PRs, that are not merged and no response from the maintainers? Sorry, but I gotta agree with @RobertBoes on this one. Community concerns and PRs feel overlooked. |
You're right, I wasn't here back then, so I don't always know about the motivations at the time, but I'm sure it was with the best intentions. But let's look forward. I'm here to help and improve Inertia. I've only closed this PR, not the issue about this (#707).
Again, I can't comment on the lack of responses from the past, but I'm here to help. Just because a PR has been opened for a long time (with or without response) doesn't mean it's automatically ready to merge. Obviously, I'm not going to merge stuff in that I already know is going to cause problems. And for the record, I just merged #731 in but without the decoding part.
That's why I've started this morning going through all the PRs and issues one by one. I'm not closing anything without carefully reviewing it. |
I think we all are looking forward. The state of it is: It's not going to be fixed in the foreseeable future. You're proposing the same solution that was already proposed months ago. I could've updated this PR to use that solution, or resubmit a PR that uses that solution. Instead, it's closed, signaling an end of discussion. Neither is the issue updated with a proposal.
And you're sure that PR doesn't introduce breaking changes? Looking at that PR, the author talks about trailing slashes being a real thing, while the linked article mentions the opposite. Laravel itself does basically everything without trailing slashes. For example, if you use a paginator, the links it'll generate are without a trailing slash. Redirects are done without a trailing slash. Currently, Inertia will always use an URL without trailing slash, so this actually helps mitigate an incorrect webserver setup. This means Inertia follows how Laravel does URL generation. With this PR, you introduce more inconsistency. |
I really hope I won't need to create a custom urlResolver on every project just so that params are not encoded, like they should be. |
In #592 URL generation was fixed regarding sub paths. However it did introduce encoding issues; #592 (comment)
With this PR it simply decodes the URL to an unencoded variant, which would then be used on the client to set the current location.