Skip to content
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

No encode, decode in createLocation #465

Merged
merged 6 commits into from Jun 10, 2017
Merged

No encode, decode in createLocation #465

merged 6 commits into from Jun 10, 2017

Conversation

pshrmn
Copy link
Contributor

@pshrmn pshrmn commented Apr 21, 2017

Removes the automatic encoding of pathnames, leaving that up to the browser.

Moves the decoding to createLocation because 1) that is now used by the getDOMLocation calls to create a location and 2) we should ensure that if a user pushes a location whose pathname is encoded, we decode it for consistency.

@@ -21,6 +21,7 @@ const execSteps = (steps, history, done) => {
if (index === steps.length)
cleanup()
} catch (error) {
console.log('caught error', error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you wanna leave this in?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh bother. That's the remnant of my debugging when I accidentally passed done to a describe call instead of an it call.

},
(location) => {
expect(location).toMatch({
pathname: '/view/#abc'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not actually sure about this test case. It passes, but I'm not sure if the behavior is desirable. This only happens if the user passes a bad location object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the kind of thing we don't actually need to test. i.e. if anyone actually tried to do this I'd probably just tell them to use hash instead of putting it on the pathname.

Copy link
Contributor Author

@pshrmn pshrmn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and added two encoding checks. My thoughts are:

Throwing when given a bad path but also creating locations from bad paths is inconsistent. We should probably just choose one.

I was curious how Express deals with bad percent-encoding and when I used a wildcard path, it failed, but with no path it worked. I think that users would typically provide a pattern to match against, so that would be in favor or throwing an error.

// when requesting /test%
app.use('*', function() {...}) // throws URIError
app.use(function() {...}) // did not throw

RFC 3986 2.4 states:

Because the percent ("%") character serves as the indicator for
percent-encoded octets, it must be percent-encoded as "%25" for that
octet to be used as data within a URI.

That, too, seems to indicate that we should treat a bad percent-encoding as an error.

location.pathname = decodeURI(location.pathname)
} catch (e) {
if (e instanceof URIError) {
warning(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we try to create a location with a bad percent-encoding, we swallow the error, keep location.pathname encoded, and log a warning.

throw new Error(
'You are attempting to create a path that cannot be decoded. ' +
'Please call encodeURI on the pathname.'
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A slightly more useful error than the default Uncaught URIError: URI malformed

@pshrmn
Copy link
Contributor Author

pshrmn commented Apr 22, 2017

Updated to just throw in createLocation when a pathname cannot be decoded. I believe that this makes the most sense to do, although it can be easily changed if you think otherwise @mjackson.

Internally, createPath is always passed a location object that was created by createLocation, so just having createLocation throw should be good enough. Having said that, createPath is exported by history, so maybe it should throw on its own?

@pshrmn
Copy link
Contributor Author

pshrmn commented Apr 24, 2017

The obvious issue with history throwing when it encounters a malformed URI is that developers will need to try...catch their code if they want to recover from bad percent-encoding. This would make it difficult to display an error page that looks like it is in their website.

try {
  ReactDOM.render((
    <BrowserRouter>
      <App />
    </BrowserRouter
  ), holder)
} catch (e) {
  ReactDOM.render((
    <MalformedURIMessage />
  ), holder)
}

I still think that history should throw and we can point to the RFC 3986 path parser rules to justify that, but there will still probably be people who want to use malformed URIs for some reason. I don't necessarily like the idea of automatically using the encoded pathname if the decode fails, but I think that it might be useful in the future to add an explicit "no decode" mode.

@nil4
Copy link

nil4 commented Apr 26, 2017

I still think that history should throw and we can point to the RFC 3986 path parser rules to justify that, but there will still probably be people who want to use malformed URIs for some reason

@pshrmn I think this is the right approach; an app using an invalid/malformed path can always be fixed to encode correctly. Thank you for fixing this.

@pshrmn
Copy link
Contributor Author

pshrmn commented May 30, 2017

Just bumping this since it has been a while. Whether or not this is the best approach, something definitely should be done here since the current implementation (made by myself ☹️) breaks things.

@nil4
Copy link

nil4 commented Jun 5, 2017

@pshrmn I would love to see this added. 👍

@mjackson
Copy link
Member

This looks good to me. Thanks, @pshrmn!

@mjackson mjackson merged commit 4aeb669 into remix-run:master Jun 10, 2017
@mjackson
Copy link
Member

mjackson commented Jun 10, 2017

Seems like this should probably be a patch release since we're just fixing a bug we introduced in 4.6.0. Would you agree?

@pshrmn
Copy link
Contributor Author

pshrmn commented Jun 10, 2017

I agree. More of a bug fix than "added functionality", so I don't think that it would warrant a minor bump.

@pshrmn
Copy link
Contributor Author

pshrmn commented Jun 12, 2017

As a minor addendum, the next release would also include #459, but that is also pretty much just a bug fix, so I don't think that it warrants a minor bump.

@pshrmn
Copy link
Contributor Author

pshrmn commented Jun 12, 2017

One more thing I just remembered is that #485 needs to be addressed before the next release.

@timdorr
Copy link
Member

timdorr commented Jun 13, 2017

OK, just got that one in for you.

@mjackson Did you want to push out a 4.6.2 release or add me to npm so I can take care of that for you? (you probably should add Ryan, BTW 😄)

@mjackson
Copy link
Member

Thanks, @timdorr. I'll go ahead and cut the release :)

@lock lock bot locked as resolved and limited conversation to collaborators Jan 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants