1
myscheme:?id=test

If I pass this to [NSURL URLWithString:] and print its query property, I get nil, but if I put a slash right after the colon (or two or three) it works fine.

Is this actually an invalid URL or is it a bug in NSURL?

According to some research, it appears to be a valid URL. From http://url.spec.whatwg.org/:

An absolute URL must be a scheme, followed by ":", followed by scheme data, optionally followed by "?" and a query.

and (emphasis added)

The syntax of scheme data depends on the scheme and is typically defined alongside it. For a relative scheme, scheme data must be a scheme-relative URL. For other schemes, specifications or standards must define scheme data within the constraints of zero or more URL units.

devios1
  • 36,899
  • 45
  • 162
  • 260
  • 1
    That URL works fine for me. I use myscheme:?id=test and NSURL returned non-nil. And when I subsequently wrote an app that registered that scheme, it successfully was invoked using that URL, too. Personally, I would always use a scheme data, but it doesn't appear that you have to. – Rob Oct 14 '13 at 03:00
  • I guess the problem is the url doesn't recognize the *query* portion of the url (changed title to reflect this). Perhaps it is simply treating the query as scheme data, but that still seems wrong according to the definition. – devios1 Oct 14 '13 at 19:17
  • Turns out it is being stored in the `resourceSpecifier` property of `NSURL`. And in fact, I can even omit the `?` and it will still interpret it as such, so that's acceptable. As long as I can get to the data I don't really care how `NSURL` interprets it. – devios1 Oct 14 '13 at 19:40
  • Sorry, I didn't read your question carefully enough. I was responding to the title. For what it's worth, it might be safer to use a URL with the `/` in case Apple ever changes this behavior to parse the `?id=test` as the query. Glad you solved the problem, nonetheless. – Rob Oct 14 '13 at 19:50

2 Answers2

2

myscheme:?id=test is a valid URL, and NSURL recognises it as such, by returning non-nil from +URLWithString:.

However, by RFC 1808, it doesn't conform in a manner such that NSURL recognises the ? character as indicating a query string, so -query returns nil.

The good news here is that NSURLComponents has a slightly different parser which will recognise the ? as indicating a query for your example:

NSURLComponents *components = [NSURLComponents componentsWithString:@"myscheme:?id=test"];
return components.query; // returns @"id=test"

If you still need to target iOS 6 or earlier with this code, I suggest using my KSURLComponents class instead, which takes the same parsing approach.

Mike Abdullah
  • 14,933
  • 2
  • 50
  • 75
1

Just answering the part in the title (Is this a valid URL?), without taking NSURL into account (which I don’t know; it might be possible that NSURL doesn’t need valid URLs at all).

myscheme:?id=test is not a valid URL, because myscheme is not a registered URI scheme. You can find all valid URI schemes at http://www.iana.org/assignments/uri-schemes.html.

Each URI scheme specifies the valid scheme data on its own, but the syntax has to match the grammar for absolute URIs:

URI scheme specifications must define their own syntax so that all strings matching their scheme-specific syntax will also match the grammar, as described in Section 4.3.

The syntax is defined as:

absolute-URI  = scheme ":" hier-part [ "?" query ]

But hier-part may be empty (if I didn’t overlook anything in STD 66). So if you are using a valid URI scheme, your URI seems to be valid (as long as that URI scheme doesn’t define special rules for the scheme data, which it probably does).

unor
  • 92,415
  • 26
  • 211
  • 360
  • I think it's incorrect to say a scheme must be registered for a URL to be valid. None of the RFCs say this, and the document you are quoting that does is a "living standard document" that, as of late December 2013, has a bright red box with ellipses next to the phrase, presumably indicating that statement is still being considered and revised. – algal Dec 27 '13 at 19:47
  • @algal: [STD 66, section 3.1](http://tools.ietf.org/html/std66#section-3.1) says: "Each URI begins with a scheme name that refers to a specification for assigning identifiers within that scheme." Some lines below: "The scheme registry maintains the mapping between scheme names and their specifications." It refers to [BCP 35](http://tools.ietf.org/html/bcp35), wich says in [section 1](http://tools.ietf.org/html/bcp35#section-1): "there is a single namespace for registered values" (in contrast to what the obsoleted RFC 2717 defined). – unor Dec 27 '13 at 20:27
  • Interesting. So if we suppose the implication is that the scheme registry maintains the mapping of _all_ scheme names, then it's not a scheme name if it's not registered, and then it's not a URL. Ok. But that sure leaves a hell of a lot of URLs floating around that are invalid but well-formed! :) – algal Dec 27 '13 at 20:52
  • @algal: (Note that all this is only me digging in the RFC‘s, I don’t have firm knowledge here; I’d love to be corrected.) Yes, I think so. [Anyone](http://tools.ietf.org/html/bcp35#section-3) could register schemes that are already in use: "Previously unregistered URI schemes discovered in use may be registered by third parties on behalf of those who created the URI scheme". -- However, without such a (registered) specification we can only know to some extent if it would be "well-formed", as scheme specs could define additional rules for the URI syntax. – unor Dec 27 '13 at 21:05
  • Agreed. It seems like there's a tension between the world of the specs, which envision public URIs exchanged over the network, and the real world. The latter also includes a proliferation of private URLs, confined to one host or even to one process, where they serve as a DSL for naming records and decomposing resource loading. OS X provides URLs for individual address book records, mail records, calendar records, etc.. For me, all motivated by my question: http://stackoverflow.com/questions/20807430/custom-url-scheme-as-adapter-on-existing-url-schemes – algal Dec 27 '13 at 21:30
  • The WHATWG URL spec seems to have changed. Instead of "must", it now says "should": https://url.spec.whatwg.org/#url-syntax – unor Feb 01 '17 at 15:39