代码之家  ›  专栏  ›  技术社区  ›  John Leidegren

什么是有效的,什么不在uri查询中?

  •  79
  • John Leidegren  · 技术社区  · 15 年前

    背景(进一步的问题)

    我一直在搜索这个来回阅读RFC,所以问题试图破解这一点,但我仍然没有杰克。

    所以我想我们只要投票给“最佳”答案就行了,还是?

    基本上可以归结为这个。

    3.4。查询组件

    查询组件是要由资源解释的信息字符串。

    query = *uric

    在查询组件中,字符“;”、“/”、“?”保留、“:”、“@”、“&”、“=”、“+”、“,”和“$”。

    首先让我困惑的是尿的定义是这样的

    uric = reserved | unreserved | escaped

    reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

    然而,这一点在一些段落中得到了澄清,比如

    上面的“reserved”语法类是指那些在uri中允许的字符,但在通用uri语法的特定组件中可能不允许;它们用作第3节中描述的组件的分隔符。

    “保留”集中的字符不是在所有上下文中都保留的。任何给定uri组件中实际保留的字符集由该组件定义。一般来说,如果用转义的us-ascii编码替换字符,则在uri的语义发生更改时保留字符。

    最后一个节选感觉有些倒退,但它清楚地指出,保留字符集取决于上下文。然而,3.4声明所有的保留字符都是在查询组件中保留的,然而,唯一会改变这里语义的是转义问号(?)因为uri没有定义查询字符串的概念。

    在这一点上,我已经完全放弃了rfc,但发现rfc 1738特别有趣。

    http url的形式如下:

    http://<host>:<port>/<path>?<searchpart>

    在<路径>和<搜索部件>组件中,“/”,“;”,“?”是保留的。可以在http中使用“/”字符来指定层次结构。

    我至少对RFC1738取代RFC2396的HTTP URL进行了解释。因为uri查询没有查询字符串的概念,而且reserved的解释也不允许我像现在这样定义查询字符串。

    问题

    当我想传递一个数字列表和另一个资源的请求时,这一切就开始了。我没多想,只是把它作为逗号分隔的值传递。令我惊讶的是,逗号却被去掉了。查询 page.html?q=1,2,3 编码变成 page.html?q=1%2C2%2C3 它工作了,但它很难看,没想到。就在那时,我开始浏览RFC。

    我的第一个问题很简单,编码逗号真的有必要吗?

    我的回答,根据RFC 2396:是,根据RFC 1738:否

    后来我找到了关于请求之间传递列表的相关帖子。而csv方法也同样糟糕。结果却出现了(以前没见过)。

    page.html?q=1;q=2;q=3
    

    我的第二个问题,这是一个有效的网址吗?

    我的回答,根据RFC 2396:不,根据RFC 1738:不(;保留)

    我对传递csv没有任何问题,只要它是数字,但是的,如果其他东西突然需要逗号,您确实会遇到来回编码和解码值的风险。不管怎样,我用asp.net尝试了分号查询字符串,结果并不是我所期望的那样。

    Default.aspx?a=1;a=2&b=1&a=3
    
    Request.QueryString["a"] = "1;a=2,3"
    Request.QueryString["b"] = "1"
    

    我看不出这与csv方法有多大的不同,因为当我请求“a”时,会得到一个字符串,其中包含逗号。NET当然不是一个引用实现,但它还没有让我失望。

    但最重要的是——我的第三个问题——这个规范在哪里?你会做什么或者不做什么?

    7 回复  |  直到 7 年前
        1
  •  61
  •   yonran    10 年前

    在通用url组件中保留字符并不意味着当它出现在组件中或组件中的数据中时必须对其进行转义。字符还必须在通用语法或特定于方案的语法中定义为分隔符,并且字符的外观必须在数据中。

    通用uri的当前标准是 RFC 3986 ,也就是说:

    2.2. Reserved Characters

    uri包括由“保留”集中的字符分隔的组件和子组件。这些字符之所以被称为“保留字符”,是因为它们可以(或不可以)由通用语法、每个特定于方案的语法或uri的解引用算法的特定于实现的语法定义为分隔符。如果uri组件的数据 与保留字符用作分隔符的目的冲突 [强调已添加],则在形成uri之前,必须对冲突数据进行百分比编码。

       reserved    = gen-delims / sub-delims
    
       gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
    
       sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
                   / "*" / "+" / "," / ";" / "="

    3.3. Path Component

    […]
    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
    […]

    3.4 Query Component

    […]
          query       = *( pchar / "/" / "?" )

    因此,在查询字符串中显式地允许使用逗号,并且仅当特定方案将逗号定义为分隔符时,才需要在数据中转义逗号。http方案不使用逗号或分号作为查询字符串中的分隔符,因此不需要对它们进行转义。浏览器是否遵循这一标准是另一回事。

    对于字符串数据,使用csv应该可以很好地工作,您只需遵循标准csv约定,要么引用数据,要么用反斜杠转义逗号。

    至于rfc 2396,它还允许在http查询字符串中使用非转义逗号:

    2.2. Reserved Characters

    许多uri包括由 特殊字符。这些字符称为“保留”,因为 它们在uri组件中的使用仅限于其保留的 目的。如果uri组件的数据与 保留用途,则冲突数据必须在 正在形成uri。

    由于逗号在http方案下没有保留的用途,因此它们不必在数据中转义。第2.3节中关于保留字符的注释是,当百分比编码时,那些改变语义的字符通常只适用;字符可以百分比编码,而不改变特定方案的语义,但仍然是保留的。

        2
  •  15
  •   Ian Kemp    8 年前

    为了回答查询字符串中的有效内容,我检查了发出请求时哪些特殊字符被chrome替换:

    Space -> %20
    ! -> !
    " -> %22
    # -> removed, marks the end of the query string
    % -> %
    & -> &
    ' -> %27
    ( -> (
    ) -> )
    * -> *
    + -> + (this usually means blank when received at the server, so encode if necessary)
    , -> ,
    - -> -
    . -> .
    / -> /
    : -> :
    ; -> ;
    < -> %3C
    = -> =
    > -> %3E
    ? -> ?
    @ -> @
    [ -> [
    \ -> \
    ] -> ]
    ^ -> ^
    _ -> _
    ` -> `
    { -> {
    | -> |
    } -> }
    ~ -> ~
    
    Extended ASCII (like °) -> Every character from this set is encoded
    

    注意:这可能并不意味着您不应该转义在为链接生成uri时没有被替换的字符。例如,通常建议不要使用 ~ 在uri中,因为兼容性问题,但它仍然是有效字符。

    另一个例子是加号,它是有效的,但当服务器将其作为请求的一部分接收时,通常被视为编码空白。因此,即使它的目的是表示一个加号而不是一个空格,它也应该被编码。

    因此,要回答应该编码的内容:无效字符和您想逐字处理但有特殊含义或可能在服务器端造成问题的字符。

        3
  •  9
  •   Nas Banov    11 年前

    只使用 ?q=1+2+3

    我在这里回答了第四个问题:)这个问题并没有问,而是以:我如何传递数字列表a-la逗号分隔值开始的?在我看来,最好的方法是将它们分隔开来,让空格将url表单编码到 + . 很好,只要你知道列表中的值不包含空格(数字往往不包含空格)。

        4
  •  5
  •   bobince    13 年前

    页面?q=1;q=2;q=3

    这是有效的网址吗?

    对。这个 ; 已被保留,但不是由RFC保留。定义此组件的上下文是 application/x-www-form-urlencoded 媒体类型,它是HTML标准的一部分(节 17.13.4.1 )特别是隐藏在章节里的那张偷偷摸摸的纸条 B.2.2 :

    我们建议http服务器实现者,特别是cgi实现者支持使用“;”代替“&”来避免作者以这种方式转义“&”字符的麻烦。

    不幸的是,许多流行的服务器端脚本框架(包括asp.net)不支持这种用法。

        5
  •  1
  •   momo    12 年前

    我想指出 page.html?q=1&q=2&q=3 也是有效的URL。这是在查询字符串中表示数组的完全合法的方法。您的服务器技术将决定它到底是如何呈现的。

    在经典的asp中,您可以检查 Response.QueryString("q").Count 然后使用 Response.QueryString("q")(0) (和(1)和(2))。

    请注意,您在您的asp.net中也看到了这一点(我认为这不是有意的,但请看):

    Default.aspx?a=1;a=2&b=1&a=3
    
    Request.QueryString["a"] = "1;a=2,3"
    Request.QueryString["b"] = "1"
    

    注意分号被忽略,所以 a 定义了两次,得到了两次值,用逗号分隔。使用所有与号 Default.aspx?a=1&a=2&b=1&a=3 将屈服 作为“1,2,3”。但我确信有一个方法可以获取每个单独的元素,以防元素本身包含逗号。这只是非索引查询字符串的默认属性,它将子值与逗号分隔符连接在一起。

        6
  •  1
  •   Community CDub    7 年前

    我也有同样的问题。超链接的URL是第三方URL,需要格式为的参数列表 page.html?q=1,2,3 只有和网址 page.html?q=1%2C2%2C3 不起作用。我可以使用javascript使它正常工作。可能不是最好的方法,但可以查看解决方案 here 如果对任何人都有帮助。

        7
  •  -3
  •   T.Todua Laurent W.    7 年前

    如果要将编码字符发送到 闪存/ SWF 文件,然后你应该编码字符两次!!(因为flash解析器)