簡體   English   中英

在相對部分中使用多個斜杠解析URI

[英]Resolve URI with multiple slashes in relative part

我必須在perl中編寫一個腳本來解析html中的uris。 無論如何,真正的問題是如何解決相對的尿失禁。

我有基本URI(HTML中的基本href),例如http:// a / b / c / d; p?q (讓我們通過rfc3986 )和其他不同的URI:

/ g,// g,/// g,//// g,h // g,g //// h,h /// g:f

在此RFC的5.4.1節(上面的鏈接)中,僅提供// g的示例:

“ // g” =“ http:// g

那其他所有情況呢? 據我從rfc 3986第3.3節了解,允許使用多個斜杠。 那么,遵循分辨率是否正確?

“ /// g” =“ http:// a / b / c ////

或者應該是什么? 有沒有人可以更好地解釋它,並且不用RFC或文檔就可以證明它?

更新#1 :嘗試查看此工作網址-https:///stackoverflow.com////////a/////10161264/////6618577

這里發生了什么?

首先,確認您提供的所有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 ) ] )開始。

相反,它遵循以下模式:

"//" 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//gg////hh///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"

大多數服務器將對它們進行相同的處理(這很好,因為服務器可以隨意使用任意方式解釋路徑),但是在應用相對路徑時會有所不同。 例如,如果這些是../../e的基本URI,您將得到

http://host/a/b/c/d + ../../e = http://host/a/e

http://host/a/b/c//d + ../../e = http://host/a/b/e

我很好奇Mojo :: URL會做什么,所以我檢查了一下。 有一個很大的警告,因為它並不聲稱嚴格合規:

Mojo :: URL實現了RFC 3986,RFC 3987和統一資源定位符的URL生活標准的子集,並支持IDNA和IRI。

這是程序。

my @urls = qw(/g //g ///g ////g h//g g////h h///g:f
    https:///stackoverflow.com////////a/////10161264/////6618577
    );
my @parts = qw(scheme host port path query);
my $template = join "\n", map { "$_: %s" } @parts;

my $base_url = Mojo::URL->new( 'http://a/b/c/d;p?q' );

foreach my $u ( @urls ) {
    my $url = Mojo::URL->new( $u )->base( $base_url )->to_abs;

    no warnings qw(uninitialized);
    say '-' x 40;
    printf "%s\n$template", $u, map { $url->$_() } @parts
    }

這是輸出:

----------------------------------------
/g
scheme: http
host: a
port:
path: /g
query: ----------------------------------------
//g
scheme: http
host: g
port:
path:
query: ----------------------------------------
///g
scheme: http
host: a
port:
path: /g
query: ----------------------------------------
////g
scheme: http
host: a
port:
path: //g
query: ----------------------------------------
h//g
scheme: http
host: a
port:
path: /b/c/h/g
query: ----------------------------------------
g////h
scheme: http
host: a
port:
path: /b/c/g/h
query: ----------------------------------------
h///g:f
scheme: http
host: a
port:
path: /b/c/h/g:f
query: ----------------------------------------
https:///stackoverflow.com////////a/////10161264/////6618577
scheme: https
host:
port:
path: /stackoverflow.com////////a/////10161264/////6618577
query:

不- ///g似乎更等同於/g “點段” ... 是用於通過http URL在層次結構中上下導航的內容。 另請參閱URI模塊以處理URI中的路徑。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM