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.
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, becausemyscheme
is not a registered URI scheme. You can find all valid URI schemes at http://www.iana.org/assignments/uri-schemes.html.http://tools.ietf.org/html/std66#section-3.1:
http://url.spec.whatwg.org/#writing:
Each URI scheme specifies the valid scheme data on its own, but the syntax has to match the grammar for absolute URIs:
The syntax is defined as:
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).myscheme:?id=test
is a valid URL, andNSURL
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
returnsnil
.The good news here is that
NSURLComponents
has a slightly different parser which will recognise the?
as indicating a query for your example: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.