Skip to content

Slash encoding #1645

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

Closed
ashgibson opened this issue Dec 18, 2014 · 23 comments
Closed

Slash encoding #1645

ashgibson opened this issue Dec 18, 2014 · 23 comments
Labels

Comments

@ashgibson
Copy link

I am still getting the problem when trying to pass dates.

ui-sref="jobs-list({quote_due_from:'18/12/2014',quote_due_to:'18/12/2014'})"

The following URL is generated:

http://{mydomain}/#/jobs?quote_due_from=18%252F12%252F2014&quote_due_to=18%252F12%252F2014

This is my state provider code:

module.config(function($stateProvider) {
    $stateProvider
        .state('jobs-list', {
            url: '/jobs?quote_due_from&quote_due_to&quote_followup_from&quote_followup_to&start_date_from&start_date_to&quote_status_id',
            controller: 'JobsListCtrl',
            templateUrl: 'jobs/jobs.list.html'
        });
});

I am using the latest version of ui.router

"name": "angular-ui-router",
"version": "0.2.13",
@kcjmowright
Copy link

I got around this issue by explicitly configuring the parameter types to 'any'. Behind the scenes, ui router wraps search parameters into ArrayTypes but will use the encode/decode callbacks for the wrapped type. By default, it treats query parameters as strings. And for some reason ( scratching my head, why you'd ever want to double encode the forward slash ) it will double encode forward slashes.

module.config(function($stateProvider) {
    $stateProvider
        .state('jobs-list', {
            url: '/jobs?{quote_due_from:any}&{quote_due_to:any}&{quote_followup_from:any}&{quote_followup_to:any}&{start_date_from:any}&{start_date_to:any}&quote_status_id',
            controller: 'JobsListCtrl',
            templateUrl: 'jobs/jobs.list.html'
        });
});

@tweinerpq
Copy link

Hi,
I'm still experiencing double encoding when the string I'm sending in is part of the URL, like so:
example.com/id

I'm sending in this:
<a ui-sref="search.doc({ id: 'CBVPPYMD10.1017/S003329171400227X' })" ...

and on click I'm seeing on my browser

url.com/editor/CBVPPYMD10.1017%252FS003329171400227X

I'm also seeing this same doubly encoded string as the href attribute generated by ui-router on Inspect Element.

My real doc id is CBVPPYMD10.1017/S003329171400227X

I just updated to @Version v0.2.15 and I have latest angular (1.4)

Thanks.

@tweinerpq
Copy link

Oh, I see that this is being addressed here?
#2071

Is this supposed to be fixed?

@christianliebel
Copy link

@tweinerpq #2071 won’t change the “double encoding” of the slash in the URL, however it will fix the decoding, so the encoded slash from the URL (%252F) is correctly decoded to the slash character (/) in the state params, as soon as the PR is merged.

@JakobJingleheimer
Copy link
Contributor

+1

The problem comes from UrlMatcherFactory.js:360. The value is encoded on line 338, and then that encoded value is passed to encodeURIComponent on line 360:

/* 338 */ var encoded = param.type.encode(value);
// …
/* 360 */ encoded = map(encoded, encodeURIComponent).join('&' + name + '=');

@zgmnkv
Copy link

zgmnkv commented Aug 15, 2015

I have made some research on this.
Actual problem is in valToString function urlMatcherFactory.js:572

  function valToString(val) { return val != null ? val.toString().replace(/\//g, "%2F") : val; }
  function valFromString(val) { return val != null ? val.toString().replace(/%2F/g, "/") : val; }

  var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {
    string: {
      encode: valToString,
      decode: valFromString,

This behavior was introduced in 3045e41 and 0c983a0 fixing #1119
Seems that it fixes path params, but breaks search params
Maybe we should encode/decode path params and search params differently

@zivc
Copy link

zivc commented Aug 25, 2015

Solution here: #1119 (comment)

@mismith
Copy link

mismith commented Aug 25, 2015

Not in Chrome, @zivc
See: #1119 (comment)

@frogomatic
Copy link

Is there any reason why one would ever want to encode the slash (via valToString) and then encodeURIComponent on top of that, either in parameters or in a path component?

@leye0
Copy link

leye0 commented Nov 9, 2015

What I don't like is that the href is shown with an encoded slash when passing a url with a slash as a parameter to ui-sref: site.com/page%2Fhome. I feel like this is not good when search engines are crawling the website for links.

@gligoran
Copy link

Any update on this bug? It's causing me a few problems. It's not only that the slashes are double-encoded, but it make decoding them wrong, because by manually replacing those slashes you take them out of step with the rest of encoding/decoding.

For example let's say this is URL: http://example.com/q=/--+

The proper way to encode it would be: http://example.com/q=%2f--%2b

But because of the manual slash encoding by uiRouter and then usage of encodeURIComponent the resulting URL is this: http://example.com/q=%252f--%2b

Now when you try to decode the q parameter you get %2f--+ and if you try to do it again, you get /-- (the last character is a space).

This might be a simple example, but in my case this is causing me a lot of problems with email confirmation tokens.

@nguillaumin
Copy link

We are experiencing a similar problem: One of the parameter in our routes is a URL, e.g. /something/:url meaning that it needs to be properly encoded for it to work. We spent some time investigating that and we have I think a good grasp of it so I'll dump our analysis here in the hope it will be helpful in finding a solution.

Pre-requisite reading: http://blog.lunatech.com/2009/02/03/what-every-web-developer-must-know-about-url-encoding

I think the core of the problem is that we need to consider that we're inside the fragment part of the browser URL, e.g. http://example.com/angular-app/#/this-is-the-fragment-part. Values in the fragment part are encoded in a specific way where the following characters are permitted unencoded: /?:@-._~!$&'()*+,;=

On a regular (non AngularJS) link, it means you can have a valid fragment part like http://example.com/page.html#http://www.example.com/?key=value .

But within an AngularJS app you can't have that, because / is used to separate route parts http://www.example.com/angular-app/#/route/child-route/grand-child-route. If the / were left unencoded you could have http://www.example.com/angular-app/#/route/http://example.com/something.html which would result in the route parts:

  • route
  • http:
  • [empty]
  • example.com
  • something.html

What you really want is: http://www.example.com/angular-app/#/route/http:%2F%2Fexample.com%2Fsomething.html to get only 2 route parts route and http://example.com/something.html.

So I suspect the solution is to encode/decode the values following the rules for URL fragment parts but to make an exception just for slashes. Not respecting the fragment rules may cause problems with other special chars ``/?:@-._~!$&'()*+,;=` . I think only the slash is special in our case.

To add to the confusion, encodeURI() and encoderURIComponent() cannot be used as-is to do this encoding because they are too aggressive and not suited to encode fragment parts. It seems to be a known problem by the AngularJS developers who come up with their own functions to do so:

Hope this helps!

@schneikai
Copy link

Same issue here. Slashes in query string parameters are getting double encoded when going through $state.go for example.

C/L becomes C%252FL where it should be C%2FL

@christopherthielen
Copy link
Contributor

This should be fixed in release 0.2.16+ We now encode slashes specially, using a custom escape character (tilde)
see 02e9866 #2071 (comment)

@conner-fallone
Copy link

Seems like this just makes an error less likely to happen by doing your own encoding with ~, while introducing another issue. What happens if ~2F is in a parameter? Then it will get decoded to a /. How come you guys aren't using encodeURIComponent?

@christopherthielen
Copy link
Contributor

christopherthielen commented Sep 22, 2016

How come you guys aren't using encodeURIComponent?

@fallXone because angular $location has special handling for splitting on '/' which causes encoded parameter values with slashes like /foo/param%2Fval/bar to be forcibly decoded to /foo/param/val/bar.

See my analysis ticket: #2598

Note: if we weren't using $location service to integrate with the URL, this wouldn't be an issue

@abhijeetahuja
Copy link

url: 'products/{slugPath:.*}'
with
url: 'products/{slugPath:any}'

@jsheffers
Copy link

Angular 1.6.7 introduced a change of how forward slashes are handled.

angular/angular.js@e06ebfd

angular/angular.js#16312

This broke our current angular app which is using url: '{aliasUrl:any}'. Has this change broken any other apps? Temporarily we've reverted back to 1.6.6 to resolve the issue.

@albertvaka
Copy link

albertvaka commented Dec 5, 2017

Broke our app too, URLs get double-encoded (%20 becomes %2520 on URLs).

@alee046
Copy link

alee046 commented Dec 9, 2017

Does anyone have any updates on this issue? It is breaking our site as well.

@albertvaka
Copy link

So, has this been fixed in 1.6.8?

@christopherthielen
Copy link
Contributor

The uirouter/angularjs test suite passes using angular 1.6.8 (it does not pass with 1.6.7)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests