|
Normalization of percent-encoding
Peter Bex
(16 Jun 2026 10:18 UTC)
|
|
Re: Normalization of percent-encoding
D Guthrie
(16 Jun 2026 12:26 UTC)
|
|
Re: Normalization of percent-encoding Peter Bex (16 Jun 2026 13:12 UTC)
|
|
Re: Normalization of percent-encoding
D Guthrie
(16 Jun 2026 14:50 UTC)
|
|
Re: Normalization of percent-encoding
Peter Bex
(17 Jun 2026 07:21 UTC)
|
On Tue, Jun 16, 2026 at 12:26:37PM +0000, D Guthrie wrote: > I think that decoding problems most often arise if you're feeding in > arbitrary data into the setters with no restriction, which is why I parse > the input strings strictly according to the ABNF and raise errors on > failure. I'm happy you at least detect such cases, but for a working programmer that's probably just going to lead to a lot of frustration with having seemingly random errors if they forgot to encode because for the common case it would "just work". That's the problem with an in-band signaling mechanism like this. It's also the exact same approach that leads to things like XSS and SQL injection. > I think it is a good idea to have encoding and decoding of paths > from a high-level representation to the low-level one! Glad you agree! > However, using a high-level representation like that internally which > makes slashes implicit, was for me unworkable when I was trying to achieve > compliance with the RFCs - the way in which path segment normalisation is > defined is a sort of stack procedure where there is special interpretation > of special dotted segments with respect to surrounding slashes. With a > representation like the above (where I tagged a path with being absolute > or relative to special-case a leading slash), I never figured out a way to > achieve exact compliance with the RFC's relative reference resolution or > the various normalisation test cases used by the other implementations. The way we handle that in our URI library is by handling absolute and relative paths as different. We store a literal "/" symbol at the front of an absolute path. We use strings for the components, so it's completely unambiguous. It's also a bit awkward in principle. At least with pattern matching, it's reasonably ergonomic. Another approach could be to mark it in a separate field in the record type and hide the difference in the path itself, but that could lead to inadvertantly treating relative and absolute paths the same. > I've come up with a test suite however so we might be able to give it > another shot and still come up with equivalent behaviour. > > Of course, compliance with these RFCs and a measure of desired/normative > behaviour is very difficult to achieve because of the lack of test suites > and comprehensive examples for normalisation. I'd emphasise the Haskell > network-uri test suite had the most relevant test cases because it is > explicitly an implementation of RFC 3986, and the more obscure test > cases are based on correspondence on the W3C's mailing lists about edge > cases. You've probably seen the test cases at the end of the SRFI. Our library is also based on Graham Klyne's Haskell URI parser. We have a *very* extensive test case, perhaps the most extensive one in the Scheme (or even OSS) ecosystem. Unfortunately, because LLM crawlers have been hitting our servers hard you can't easily browse the source or tests, but you can download a release tarball here: https://code.call-cc.org/egg-tarballs/6/uri-generic/ Or make a svn checkout of: https://anonymous:@code.call-cc.org/egg-tarballs/6/uri-generic/ (and for uri-common, just replace "generic" with "common" in those) > Well, the main reason I don't provide decoding procedures for all of an > URI's percent-encodings is because this seemed to largely be subsumed by > RFC 3987's conversions between IRIs and URIs (and vice versa), at least > for UTF-8. What about the reserved characters? In URIs, the server decides whether to treat those as special or not, so e.g. whether http://foo/a:b is the same URI or http://foo/a%3Ab cannot be decided lexically. As I said, the vast majority of users don't care and treat them as identical. Encoding and decoding those automatically is therefore a major convenience to the user. > We have the same set of reserved characters but this time we can decode > almost any other character in the universal character set as the character > proper. So `uri->iri' would let us decode (likely most of) an URI and > then still be able to use it to denote resources where IRIs are prevalent, > like RDF or JSON-LD. This is actually an interpretation of the > percent-encodings as UTF-8, and the behaviour is well-defined in RFC 3987 > so we can probably rely on other implementations to interpret our IRIs and > URIs as we do. It works both ways so we can also encode an IRI as an URI. This works for UTF-8 but not the reserved character cases I mentioned. > For the conversion of IRIs to URIs, as far as I understand the current > approach for non-UTF-8 encodings is to represent them in the UCS after > normalising from that encoding: > https://www.rfc-editor.org/info/rfc3987/#section-3.1 > For URIs alone, I'm not sure and I suspect this doesn't answer your > question. I admit to not being up-to-date on the IRI stuff. We only implement RFC3986. > I am not sure representing other character encodings than UTF-8 is so > useful, and I suspect it could be implemented in a separate library. I > could be missing something crucial here tohugh. For context, my own > interest in this is almost entirely for IRIs in the RDF world so I had no > need for scheme-specific interpretation, but I appreciate a lto of the > libraries out there put a lot more emphasis on web clients where there > may be a lot of scheme-specific decoding. Scheme-specific decoding gets really fun when you get into the weeds about query arguments. Cheers, Peter