Я начну с подтверждения того, что все предоставленные вами URI действительны, и с предоставления результата упомянутых вами разрешений URI (и результата нескольких моих собственных):
$ perl -MURI -e'
for my $rel (qw( /g //g ///g ////g h//g g////h h///g:f )) {
my $uri = URI->new($rel)->abs("http://a/b/c/d;p?q");
printf "%-20s + %-7s = %-20s host: %-4s path: %s\n",
"http://a/b/c/d;p?q", $rel, $uri, $uri->host, $uri->path;
}
for my $base (qw( http://host/a/b/c/d http://host/a/b/c//d )) {
my $uri = URI->new("../../e")->abs($base);
printf "%-20s + %-7s = %-20s host: %-4s path: %s\n",
$base, "../../e", $uri, $uri->host, $uri->path;
}
'
http://a/b/c/d;p?q + /g = http://a/g host: a path: /g
http://a/b/c/d;p?q + //g = http://g host: g path:
http://a/b/c/d;p?q + ///g = http:///g host: path: /g
http://a/b/c/d;p?q + ////g = http:////g host: path: //g
http://a/b/c/d;p?q + h//g = http://a/b/c/h//g host: a path: /b/c/h//g
http://a/b/c/d;p?q + g////h = http://a/b/c/g////h host: a path: /b/c/g////h
http://a/b/c/d;p?q + h///g:f = http://a/b/c/h///g:f host: a path: /b/c/h///g:f
http://host/a/b/c/d + ../../e = http://host/a/e host: host path: /a/e
http://host/a/b/c//d + ../../e = http://host/a/b/e host: host path: /a/b/e
Далее мы рассмотрим синтаксис относительных URI, поскольку именно этот вопрос вращается вокруг вас.
relative-ref = relative-part [ "?" query ] [ "#" fragment ]
relative-part = "//" authority path-abempty
/ path-absolute
/ path-noscheme
/ path-empty
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
path-noscheme = segment-nz-nc *( "/" segment )
path-rootless = segment-nz *( "/" segment )
segment = *pchar ; 0 or more <pchar>
segment-nz = 1*pchar ; 1 or more <pchar> nz = non-zero
Ключевые моменты из этих правил для ответа на ваш вопрос:
- Абсолютный путь (
path-absolute
) не может начинаться с //
.Первый сегмент, если имеется, должен быть ненулевым по длине.Если относительный URI начинается с //
, то в противном случае в пути может быть authority
. //
, поскольку сегменты могут иметь нулевую длину.
Теперь давайте посмотрим на каждое из предоставленных вами разрешений по очереди.
/g
- это абсолютный путь path-absolute
и, следовательно, действительный относительный URI (relative-ref
), и, следовательно,действительный URI (URI-reference
).
Анализ URI (скажем, с использованием регулярного выражения в Приложении B) дает нам следующее:
Base.scheme: "http" R.scheme: undef
Base.authority: "a" R.authority: undef
Base.path: "/b/c/d;p" R.path: "/g"
Base.query: "q" R.query: undef
Base.fragment: undef R.fragment: undef
Следуя алгоритму в §5.2.2, мы получаем:
T.path: "/g" ; remove_dot_segments(R.path)
T.query: undef ; R.query
T.authority: "a" ; Base.authority
T.scheme: "http" ; Base.scheme
T.fragment: undef ; R.fragment
Следуя алгоритму в §5.3, мы получаем:
http://a/g
//g
отличается.//g
не абсолютный путь (path_absolute
), поскольку абсолютный путь не может начинаться с пустого сегмента ("/" [ segment-nz *( "/" segment ) ]
).
Вместо этого он следует следующимpattern:
"//" authority path-abempty
Анализ URI (скажем, с использованием регулярного выражения в Приложении B) дает нам следующее:
Base.scheme: "http" R.scheme: undef
Base.authority: "a" R.authority: "g"
Base.path: "/b/c/d;p" R.path: ""
Base.query: "q" R.query: undef
Base.fragment: undef R.fragment: undef
Следуя алгоритму в §5.2.2, мы получаем следующее:
T.authority: "g" ; R.authority
T.path: "" ; remove_dot_segments(R.path)
T.query: "" ; R.query
T.scheme: "http" ; Base.scheme
T.fragment: undef ; R.fragment
Следуя алгоритму в §5.3, мы получаем следующее:
http://g
Примечание : Этот сервер контактов g
!
///g
аналогичен //g
, за исключением того, что права доступа не указаны!Это удивительно верно.
Анализ URI (скажем, с использованием регулярного выражения в Приложении B) дает нам следующее:
Base.scheme: "http" R.scheme: undef
Base.authority: "a" R.authority: ""
Base.path: "/b/c/d;p" R.path: "/g"
Base.query: "q" R.query: undef
Base.fragment: undef R.fragment: undef
Следуя алгоритму в §5.2.2, мы получаем следующее:
T.authority: "" ; R.authority
T.path: "/g" ; remove_dot_segments(R.path)
T.query: undef ; R.query
T.scheme: "http" ; Base.scheme
T.fragment: undef ; R.fragment
Следуя алгоритму в §5.3, мы получаем следующее:
http:///g
Примечание : Хотя этот URI действителен, он бесполезен, поскольку имя сервера (T.authority
) пустое!
////g
совпадает с///g
за исключением R.path
равным //g
, поэтому мы получаем
http:////g
Примечание : хотя этот URI действителен, он бесполезен, поскольку имя сервера (T.authority
)пусто!
Последние три (h//g
, g////h
, h///g:f
) - все относительные пути (path-noscheme
).
ПарсингURI (скажем, с использованием регулярного выражения в Приложении B) дает нам следующее:
Base.scheme: "http" R.scheme: undef
Base.authority: "a" R.authority: undef
Base.path: "/b/c/d;p" R.path: "h//g"
Base.query: "q" R.query: undef
Base.fragment: undef R.fragment: undef
Следуя алгоритму в п. 5.2.2, мы получаем следующее:
T.path: "/b/c/h//g" ; remove_dot_segments(merge(Base.path, R.path))
T.query: undef ; R.query
T.authority: "a" ; Base.authority
T.scheme: "http" ; Base.scheme
T.fragment: undef ; R.fragment
По алгоритмув §5.3 мы получаем следующее:
http://a/b/c/h//g # For h//g
http://a/b/c/g////h # For g////h
http://a/b/c/h///g:f # For h///g:f
Я не думаю, что примеры подходят для ответа на то, что, на мой взгляд, вы действительно хотите знать.
Посмотрите на следующие два URI.Они не эквивалентны.
http://host/a/b/c/d # Path has 4 segments: "a", "b", "c", "d"
и
http://host/a/b/c//d # Path has 5 segments: "a", "b", "c", "", "d"
Большинство серверов будут обращаться с ними одинаково - что хорошо, так как серверы могут свободно интерпретировать пути вкак угодно, но это имеет значение при применении относительных путей.Например, если бы это был базовый URI для ../../e
, вы бы получили
http://host/a/b/c/d + ../../e = http://host/a/e
и
http://host/a/b/c//d + ../../e = http://host/a/b/e