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


100

배경 (아래 질문)

나는 이것을 풀기 위해 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은 확실히 참조 구현은 아니지만 아직 실망시키지 않았습니다.

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


RFC 1738이 RFC 2396을 대체 할 수있는 방법은 무엇입니까?
Matthew Flaschen

1
URL과 실질적으로 의미가있는 것은 내 해석이다. (대체는 아마도 올바른 단어가 아닐 것입니다. RFC 용어에서 더 이상 사용되지 않는 오래된 RFC에 사용 되었기 때문에 RFC 1738은 검색 부분에 쿼리 문자열을 넣을 수있는 유일한 사양 일 때 더 이상 사용되지 않는다고 느끼지 않습니다. of the URL)
John Leidegren

답변:


69

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

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

2.2. 예약 된 문자

URI에는 "예약 된"집합의 문자로 구분 된 구성 요소 및 하위 구성 요소가 포함됩니다. 이러한 문자는 일반 구문, 각 체계 별 구문 또는 URI 역 참조 알고리즘의 구현 별 구문에 의해 구분 기호로 정의 될 수도 있고 정의되지 않을 수도 있기 때문에 "예약 됨"이라고합니다. URI 구성 요소에 대한 데이터 가 구분 기호 (강조 추가됨) 로서 예약 된 문자의 목적과 충돌하는 경우 URI가 형성되기 전에 충돌 데이터를 퍼센트 인코딩해야합니다.

   예약 됨 = Gen-delims / sub-delims

   gen-delims = ":"/ "/"/ "?" / "#"/ "["/ "]"/ "@"

   하위 항목 = "!" / "$"/ "&"/ " '"/ "("/ ")"
               / "*"/ "+"/ ","/ ";" / "="

3.3. 경로 구성 요소

[...]
pchar = 예약되지 않음 / pct 인코딩 / 하위 배달 / ":"/ "@"
[...]

3.4 쿼리 구성 요소

[...]
      쿼리 = * (pchar / "/"/ "?")

따라서 쉼표는 쿼리 문자열 내에서 명시 적으로 허용되며 특정 체계가 구분 기호로 정의하는 경우에만 데이터에서 이스케이프되어야합니다. HTTP 체계는 쿼리 문자열에서 구분 기호로 쉼표 또는 세미콜론을 사용하지 않으므로 이스케이프 할 필요가 없습니다. 브라우저가이 표준을 따르는 지 여부는 또 다른 문제입니다.

CSV를 사용하면 문자열 데이터에 대해 잘 작동합니다. 표준 CSV 규칙을 따르고 데이터를 인용하거나 백 슬래시로 쉼표를 이스케이프하면됩니다.

RFC 2396의 경우 HTTP 쿼리 문자열에 이스케이프되지 않은 쉼표도 허용됩니다.

2.2. 예약 된 문자

많은 URI에는 특정 특수 문자로 구성되거나 구분되는 구성 요소가 포함됩니다. 이러한 문자는 URI 구성 요소 내에서 사용이 예약 된 용도로 제한되기 때문에 "예약 됨"이라고합니다. URI 구성 요소의 데이터가 예약 된 목적과 충돌하는 경우 충돌하는 데이터는 URI를 형성하기 전에 이스케이프되어야합니다.

쉼표는 HTTP 체계에서 예약 된 목적이 없기 때문에 데이터에서 이스케이프 처리 할 필요가 없습니다. 예약 된 문자에 대한 § 2.3의 참고 사항은 백분율 인코딩이 적용되는 경우 의미를 변경하는 문자입니다. 문자는 특정 체계에 대한 의미를 변경하지 않고 퍼센트 인코딩 될 수 있지만 여전히 예약되어 있습니다.


23

쿼리 문자열에서 유효한 내용에 답하기 위해 요청을 할 때 어떤 특수 문자가 크롬으로 대체되는지 확인했습니다.

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 에서 사용하지 않는 것이 권장 되지만 여전히 유효한 문자입니다.

또 다른 예는 유효하지만 서버가 요청의 일부로 수신 할 때 일반적으로 인코딩 된 공백으로 처리되는 더하기 기호입니다. 따라서 공백이 아닌 플러스를 나타내는 것이 목적 일 때 유효하더라도 인코딩되어야합니다.

따라서 인코딩해야 할 내용에 대한 답 : 문자 그대로 처리하고 싶지만 특별한 의미가 있거나 서버 측에서 문제를 일으킬 수있는 잘못된 문자 및 문자.


/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b#1;c#2유효한 쿼리 매개 변수는?
Sumit Jain

@SumitJain 아니요, #URI의 쿼리 부분에있는 그대로 나타날 수 없기 때문 입니다. 이를로 인코딩해야 %23하므로 URI는 /programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b%231;c%232.
Dai

10

그냥 사용 ?q=1+2+3

나는 여기에 네 번째 질문에 대답하고 있습니다 :) 묻지 않았지만 모두 시작 : 숫자 목록 a-la 쉼표로 구분 된 값을 어떻게 전달합니까? 나에게 가장 좋은 방법은 공백으로 구분하여 전달하는 것입니다. 여기서 공백은 url-form-encoded됩니다 +. 목록의 값에 공백이 없다는 것을 아는 한 훌륭하게 작동합니다 (숫자가없는 경향이 있음).


이것은 (질문에 대한 답이 아니기 때문에) 코멘트 여야하지만, 감사합니다. +쉼표를 사용하려는 특정 경우에 훨씬 더 의미가 있습니다.
Gajus

6

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

유효한 URL입니까?

예. 는 ;하지만 아닌 RFC에 의해 예약되어 있습니다. 이 구성 요소를 정의하는 컨텍스트 application/x-www-form-urlencoded는 HTML 표준 (섹션 17.13.4.1 )의 일부인 미디어 유형 의 정의입니다 . 특히 섹션 B.2.2에 숨겨져있는 은밀한 메모 :

HTTP 서버 구현 자, 특히 CGI 구현자는 ";"사용을 지원하는 것이 좋습니다. "&"대신 "&"문자를 이러한 방식으로 이스케이프 처리하는 수고를 덜어줍니다.

불행히도 ASP.NET을 포함한 많은 인기있는 서버 측 스크립팅 프레임 워크는 이러한 사용을 지원하지 않습니다.


따라서 ?q=1;q=2;q=3쿼리가 유효하지만 모호합니다. 일부 서버 측 프레임 워크는이를 의미하는 것으로 읽고 { q: '1;q=2;q=3' }다른 프레임 워크는 { q: {'1', '2', '3'}}.
Nas Banov 2014

1
예. 더 나쁜 것은 HTML5 ;에에 대한 언어가 포함되어 있지 않아 HTML4와 HTML5가 일치하지 않는다는 것입니다. 윽, 스펙 문서에서 비 규범적인 언어의 위험 ...
bobince

@NasBanov 그럼에도 불구하고 다른 사람 (예를 들어, PHP는)로 해석합니다{ q: 3 }
니콜라스 정강이

1
@NicholasShanks-PHP가 관련된 곳에서는 모든 베팅이 해제됩니다! :)
Nas Banov

1

나는주의하고 싶은 page.html?q=1&q=2&q=3뿐만 아니라 유효한 URL입니다. 이것은 쿼리 문자열에서 배열을 표현하는 완전히 합법적 인 방법입니다. 서버 기술에 따라 정확히 표시되는 방법이 결정됩니다.

Classic ASP에서는 (and (1) and (2)) 를 확인 Response.QueryString("q").Count하고 사용 Response.QueryString("q")(0)합니다.

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를 사용하면 a"1,2,3"이됩니다. 하지만 요소 자체에 쉼표가 포함 된 경우 각 개별 요소를 가져 오는 방법이 있다고 확신합니다. 하위 값을 쉼표 구분 기호와 함께 연결하는 것은 인덱싱되지 않은 QueryString의 기본 속성 일뿐입니다.


1

나는 같은 문제가 있었다. 하이퍼 링크 된 URL은 제 3 자 URL이었고 형식의 매개 변수 목록 page.html?q=1,2,3만 예상 했고 URL page.html?q=1%2C2%2C3이 작동하지 않았습니다. 나는 자바 스크립트를 사용하여 작동시킬 수있었습니다. 최선의 접근 방식은 아니지만 누군가에게 도움이되는 경우 여기 에서 솔루션을 확인할 수 있습니다 .


-3

인코딩 된 문자를 FLASH / SWF 파일 로 보내는 경우 문자를 두 번 인코딩해야합니다 !! (플래시 파서 때문에)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.