Custom URL scheme as adapter on existing URL schem

2019-08-03 20:30发布

问题:

Is there a clean and spec-conformant way to define a custom URL scheme that acts as an adapter on the resource returned by another URL?

I have already defined a custom URL protocol which returns a decrypted representation of a local file. So, for instance, in my code,

decrypted-file:///path/to/file

transparently decrypts the file you would get from file:///path/to/file. However, this only works for local files. No fun! I am hoping that the URL specification allows a clean way that I could generalize this by defining a new URL scheme as a kind of adapter on existing URLs.

For example, could I instead define a custom URL scheme decrypted: that could be used as an adapter that prefixes another absolute URL that retrieved a resource? Then I could just do

decrypted:file:///path/to/file

or decrypted:http://server/path/to/file or decrypted:ftp://server/path/to/file or whatever. This would make my decrypted: protocol composable with all existing URL schemes that do file retrieval.

Java does something similar with the jar: URL scheme but from my reading of RFC 3986 it seems like this Java technology violates the URL spec. The embedded URL is not properly byte-encoded, so any /, ?, or # delimiters in the embedded URL should officially be treated as segment delimiters in the embedding URL (even if that's not what JarURLConnection does). I want to stay within the specs.

Is there a nice and correct way to do this? Or is the only option to byte-encode the entire embedded URL (i.e., decrypted:file%3A%2F%2F%2Fpath%2Fto%2Ffile, which is not so nice)?

Is what I'm suggesting (URL adapters) done anywhere else? Or is there a deeper reason why this is misguided?

回答1:

There's no built-in adaptor in Cocoa, but writing your own using NSURLProtocol is pretty straightforward for most uses. Given an arbitrary URL, encoding it like so seems simplest:

myscheme:<originalurl>

For example:

myscheme:http://example.com/path

At its simplest, NSURL only actually cares if the string you pass in is a valid URI, which the above is. Yes, there is then extra URL support layered on top, based around RFC 1808 etc. but that's not essential.

All that's required to be a valid URI is a colon to indicate the scheme, and no invalid characters (basically, ASCII without spaces).

You can then use the -resourceSpecifier method to retrieve the original URL and work with that.