Is this a valid URL, and if so why does NSURL not

2019-08-11 22:18发布

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.

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-08-11 22:42

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).

查看更多
淡お忘
3楼-- · 2019-08-11 22:49

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.

查看更多
登录 后发表回答