developer tip

무엇이 유효하고 URI 쿼리에없는 것은 무엇입니까?

optionbox 2020. 9. 6. 09:30
반응형

무엇이 유효하고 URI 쿼리에없는 것은 무엇입니까?


배경 (아래 질문)

나는 이것을 크랙하기 위해 RFC와 SO 질문을 읽고 앞뒤로 인터넷 검색을 해왔지만 여전히 잭이 없습니다.

그래서 저는 우리가 "최상의"답변에 투표하고 그게 다라고 생각합니다, 아니면?

기본적으로 이것으로 귀결됩니다.

3.4. 쿼리 구성 요소

쿼리 구성 요소는 리소스가 해석 할 정보 문자열입니다.

query = *uric

쿼리 구성 요소 내에서 ";", "/", "?", ":", "@", "&", "=", "+", ","및 "$"문자는 예약되어 있습니다.

나를 놀라게하는 첫 번째 것은 * uric이 이렇게 정의된다는 것입니다.

uric = reserved | unreserved | escaped

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

그러나 이것은 다음과 같은 단락에 의해 다소 명확 해집니다.

위의 "예약 된"구문 클래스는 URI 내에서 허용되지만 일반 URI 구문의 특정 구성 요소 내에서는 허용되지 않을 수있는 문자를 나타냅니다. 섹션 3에 설명 된 구성 요소의 구분 기호로 사용됩니다.

"reserved"세트의 문자는 모든 컨텍스트에서 예약되지 않습니다. 주어진 URI 구성 요소 내에 실제로 예약 된 문자 집합은 해당 구성 요소에 의해 정의됩니다. 일반적으로 문자가 이스케이프 된 US-ASCII 인코딩으로 대체되면 URI의 의미가 변경되면 문자가 예약됩니다.

이 마지막 발췌문은 다소 거꾸로 느껴지지만 예약 된 문자 집합이 컨텍스트에 따라 달라진다는 것을 분명히 나타냅니다. 그러나 3.4에서는 모든 예약 된 문자가 쿼리 구성 요소 내에 예약되어 있다고 명시하고 있지만 여기서 의미를 변경하는 유일한 것은 URI가 쿼리 문자열의 개념을 정의하지 않기 때문에 물음표 (?)를 이스케이프하는 것입니다.

이 시점에서 저는 RFC를 완전히 포기했지만 RFC 1738이 특히 흥미 롭다는 것을 알게되었습니다.

HTTP URL은 다음과 같은 형식을 취합니다.

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

<path> 및 <searchpart> 구성 요소 내에서 "/", ";", "?" 예약되어 있습니다. HTTP 내에서 "/"문자를 사용하여 계층 구조를 지정할 수 있습니다.

적어도 RFC 1738이 RFC 2396을 대체하는 HTTP URL과 관련하여 이것을 해석합니다. URI 쿼리에는 쿼리 문자열에 대한 개념이 없기 때문에 예약 된 해석으로 인해 내가 익숙한 쿼리 문자열을 정의 할 수 없습니다. 지금까지.

질문

이 모든 것은 다른 리소스의 요청과 함께 숫자 목록을 전달하고 싶을 때 시작되었습니다. 나는 그것에 대해 많이 생각하지 않고 쉼표로 구분 된 값으로 전달했습니다. 놀랍게도 쉼표가 이스케이프되었습니다. 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

두 번째 질문은 유효한 URL입니까?

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"

"a"를 요청할 때 쉼표가있는 문자열이 표시되므로 이것이 csv 접근 방식과 얼마나 다른지 알 수 없습니다. ASP.NET은 확실히 참조 구현은 아니지만 아직 실망시키지 않았습니다.

하지만 가장 중요한 것은 제 세 번째 질문입니다. 이것에 대한 사양은 어디에 있습니까? 당신은 무엇을 하시겠습니까?


문자가 일반 URL 구성 요소 내에 예약되어 있다고해서 구성 요소 또는 구성 요소의 데이터 내에 나타날 때 이스케이프되어야 함을 의미하지는 않습니다. 문자는 일반 또는 체계 특정 구문 내에서 구분 기호로 정의되어야하며 문자의 모양은 데이터 내에 있어야합니다.

일반 URI에 대한 현재 표준은 RFC 3986 이며 다음과 같이 말합니다.

2.2. 예약 된 문자

URIs include components and subcomponents that are delimited by characters in the "reserved" set. These characters are called "reserved" because they may (or may not) be defined as delimiters by the generic syntax, by each scheme-specific syntax, or by the implementation-specific syntax of a URI's dereferencing algorithm. If data for a URI component would conflict with a reserved character's purpose as a delimiter [emphasis added], then the conflicting data must be percent-encoded before the URI is formed.

   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 / "/" / "?" )

Thus commas are explicitly allowed within query strings and only need to be escaped in data if specific schemes define it as a delimiter. The HTTP scheme doesn't use the comma or semi-colon as a delimiter in query strings, so they don't need to be escaped. Whether browsers follow this standard is another matter.

Using CSV should work fine for string data, you just have to follow standard CSV conventions and either quote data or escape the commas with backslashes.

As for RFC 2396, it also allows for unescaped commas in HTTP query strings:

2.2. Reserved Characters

Many URI include components consisting of or delimited by, certain special characters. These characters are called "reserved", since their usage within the URI component is limited to their reserved purpose. If the data for a URI component would conflict with the reserved purpose, then the conflicting data must be escaped before forming the URI.

Since commas don't have a reserved purpose under the HTTP scheme, they don't have to be escaped in data. The note from § 2.3 about reserved characters being those that change semantics when percent-encoded applies only generally; characters may be percent-encoded without changing semantics for specific schemes and yet still be reserved.


To answer what's valid in a query string I checked which special characters get replaced by chrome when making a request:

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

Note: That probably doesn't mean you shouldn't escape characters that didn't get replaced when you generate URIs for links. For instance it is often recommended not to use ~ in URIs because of compatibility issues but it's still a valid character.

Another example would be the plus-sign which is valid but usually treated as encoded blank when a server receives it as part of a request. Thus it should be encoded even if valid when it's purpose is to represent a plus and not a space.

So to answer what should be encoded: Invalid characters and characters that you want to treat literally but have a special meaning or can cause trouble at the server end.


Just use ?q=1+2+3

I am answering here a fourth question :) that did not ask but all started with: how do i pass list of numbers a-la comma-separated values? Seems to me the best approach is just to pass them space-separated, where spaces will get url-form-encoded to +. Works great, as longs as you know the values in the list contain no spaces (something numbers tend not to).


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

is this a valid URL?

Yes. The ; is reserved, but not by an RFC. The context that defines this component is the definition of the application/x-www-form-urlencoded media type, which is part of the HTML standard (section 17.13.4.1). In particular the sneaky note hidden away in section B.2.2:

We recommend that HTTP server implementors, and in particular, CGI implementors support the use of ";" in place of "&" to save authors the trouble of escaping "&" characters in this manner.

Unfortunately many popular server-side scripting frameworks including ASP.NET do not support this usage.


I would like to note that page.html?q=1&q=2&q=3 is a valid url as well. This is a completely legitimate way of expressing an array in a query string. Your server technology will determine how exactly that is presented.

In Classic ASP, you check Response.QueryString("q").Count and then use Response.QueryString("q")(0) (and (1) and (2)).

Note that you saw this in your ASP.NET, too (I think it was not intended, but look):

Default.aspx?a=1;a=2&b=1&a=3

Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"

Notice that the semicolon is ignored, so you have a defined twice, and you got its value twice, separated by a comma. Using all ampersands Default.aspx?a=1&a=2&b=1&a=3 will yield a as "1,2,3". But I am sure there is a method to get each individual element, in case the elements themselves contain commas. It is simply the default property of the non-indexed QueryString that concatenates the sub-values together with comma separators.


I had the same issue. The URL that was hyperlinked was a third party URL and was expecting a list of parameters in format page.html?q=1,2,3 ONLY and the URL page.html?q=1%2C2%2C3 did not work. I was able to get it working using javascript. May not be the best approach but can check out the solution here if it helps anyone.


If you are sending the ENCODED characters to FLASH/SWF file, then you should ENCODE the character twice!! (because of Flash parser)

참고URL : https://stackoverflow.com/questions/2366260/whats-valid-and-whats-not-in-a-uri-query

반응형