나는 괜찮아 보이는 URL 에 한 번 오후를 잃었다. OAuth 콜백이 계속 실패하고 리디렉션 URI "matched" 공급자에 등록 된 것,그리고 나는 악수가 끊어진 이유를 알 수 없었다. 내가 마침내 파서에 물건을 붙여 넣었을 때 대답은 한 곳에서 경로에 후행 슬래시이고 다른 곳에서는 아무것도 없었다,더하기 a state 이중 인코딩된 매개변수입니다 %20 되었다 %2520. 사람의 눈에는 두 URL 이 동일했습니다. OAuth 서버에 그들은 서로 다른 문자열이었고,부조화를 거부하는 것이 옳았습니다.
그것이 URL의 문제입니다: 그것들은 조밀하고, 잘못 읽히기 쉽고, 사물을 깨뜨리는 세부 사항들 - 인코딩 된 슬래시, 길 잃은 포트, 반복되는 쿼리 키, 경로를 예상 한 조각 - 은 정확히 문자의 벽에 숨겨져있는 [Toolz.dev](/를 구축하고, 내가 구축 한 디버깅하는 동안 쿼리 문자열을 응시하는 데 충분한 시간을 보냅니다 URL 파서 나를 응시하기 위해. 링크를 붙여넣고 모든 구성 요소에 레이블이 지정되고 모든 쿼리 매개 변수가 테이블에서 디코딩됩니다. 이 가이드에서는 해당 구성 요소가 무엇인지, 구별이 중요한 이유 및 사용 방법을 설명합니다.
TL;DR: URL은 구성표()로 구성됩니다
https), 선택적 자격 증명(user:pass@), 호스트(example.com) 선택적 포트, 경로()가 있습니다/blog/post), 쿼리 문자열(?id=42) 및 조각(#section). 그만큼 URL 파서 browser's 자신의 WHATWG URL 엔진을 사용하여 해당 부분으로 링크를 분할하고 쿼리를 정렬된 키-값 테이블(반복된 키는 별도로 유지됨)로 디코딩하고 구성표에 대한 유효 포트를 표시하고 가정합니다https://베어 도메인을 붙여 넣는 경우. 브라우저에서 완전히 실행되므로 토큰과의 링크는 비공개로 유지됩니다.
URL의 일부는 무엇입니까?
모든 URL 은 WHATWG URL Standard - 브라우저가 실제로 구현하는 사양에 의해 정의된 동일한 문법을 따릅니다. 일단 부품의 이름을 지정할 수 있게 되면 대부분의 URL 버그가 명백해집니다. 여기 전체 해부학이 있습니다. 고의적으로 바쁜 예제를 사용하여:
https://john:[email protected]:8443/catalog/shoes?color=red&size=42#reviews
└─┬─┘ └──┬──┘└─┬──┘└──────┬────────┘└─┬─┘└──────┬──────┘└──────┬──────┘ └──┬──┘
scheme user pass hostname port path query fragment
그것을 무너뜨리는 것:
| 컴포넌트 | 예시 값 | 그것이 무엇인지 |
|---|---|---|
| 계획 | https |
프로토콜. 기본 포트와 요청 방법을 결정합니다. |
| 사용자 이름 | john |
선택적 자격 증명 @. |
| 비밀번호 | s3cret |
다음 후 선택적 자격 증명 : userinfo에서. |
| 호스트 이름 | shop.example.co.uk |
포트가 없는 도메인 또는 IP 주소입니다. |
| 포트 | 8443 |
선택 사항입니다. 생략하면 구성표 기본값으로 다시 떨어집니다. |
| 호스트 | shop.example.co.uk:8443 |
포트가 있는 경우 호스트 이름과 포트가 더해집니다. |
| 원산지 | https://shop.example.co.uk:8443 |
구성표와 호스트 - 보안에 사용되는 단위 브라우저입니다. |
| 경로 | /catalog/shoes |
호스트의 리소스 위치입니다. |
| 쿼리 | ?color=red&size=42 |
키-값 매개변수 이후 ?. |
| 조각 | #reviews |
이후 클라이언트측 앵커 #는, 서버에 결코 보내지 않았습니다. |
파서는 복사 버튼으로 이들 모두를 자신의 행으로 배치하므로 다시는 몬스터 URL 에서 호스트 이름을 직접 추출할 필요가 없습니다. 또한 원시 문자열이 숨기는 몇 가지 플래그를 지정합니다: 표시된 포트가 명시적인지 scheme's 기본값인지,호스트가 명명된 도메인인지 원시 IP 인지.
호스트 이름, 호스트 및 원본의 차이점은 무엇입니까?
이 세 사람은 끊임없이 사람들을 넘어 뜨리고 혼란은 실제 버그를 유발합니다 - CORS 실패,쿠키 범위 지정 실수,리디렉션 불일치. 그들은 동의어가 아닙니다. The WHATWG URL 표준 브라우저가 실제로 구현하는 정의이며, 출처로 간주되는 것에 대한 논쟁을 해결하는 장소입니다.
호스트 이름 도메인 또는 IP일 뿐입니다: shop.example.co.uk. 아니 포트, 아니 계획. 그것은 당신이 DNS 조회에 넣어 것입니다 것입니다.
호스트 는 호스트 이름에 포트를 더한 값입니다 하지만 포트가 URL에 있는 경우에만 가능합니다. 을 위한 shop.example.co.uk:8443 호스트는 shop.example.co.uk:8443. 평야를 위해 https://shop.example.co.uk/ 호스트와 호스트 이름은 동일하며,기본 포트 443 이 기록되지 않고 암시되어 있기 때문입니다. That "only when present" rule is metcle and is why the same site can appear to have two different hosts.
원산지 계획과 호스트가: https://shop.example.co.uk:8443. 이것은 브라우저가 가장 신경쓰는 하나의 정책인데,웹 보안의 기초인 동일 출처 정책이 호스트 이름이 아닌 출처를 비교하기 때문입니다. 두 URL 은 그들의 구성표인 호스트 이름인 경우에만 출처를 공유합니다 그리고 포트 모든 일치. http://example.com 그리고 https://example.com 계획이 다르기 때문에 출처가 다릅니다. https://example.com 그리고 https://example.com:8443 호스트 이름이 동일하더라도 포트가 다르기 때문에 원본이 다릅니다. CORS 오류로 가져오기가 실패하는 경우 일반적으로 파서에서 두 원본과 나란히 비교하는 것이 불일치를 찾아내는 가장 빠른 방법입니다.
쿼리 문자열을 어떻게 구문 분석합니까?
쿼리 문자열은 일상적인 고통의 대부분이 사는 곳입니다,왜냐하면 이것은 평평하고 탈출하지 않은 듯한 얼룩이고 실제로 구조화되어 있고 퍼센트 인코딩되어 있기 때문입니다. the parser splits it for you: everything after the ?, 고장났어 &, 각각 key=value 원래 순서로 테이블에 쌍을 디코딩하고 나열합니다.
여기서는 두 가지 행동이 중요합니다. 첫째, 디코딩. 로 쓰여지는 매개변수 q=trail%20runner 와이어에 다음과 같이 표시됩니다 trail runner 값 열에서, 왜냐하면 %20 는 퍼센트로 인코딩된 공간입니다. the raw search string은 여전히 구성 요소 목록에 그대로 표시되어 있으므로 인코딩된 형식과 디코딩된 형식을 비교할 수 있습니다. 저와 같이 이중 인코딩이 의심되는 경우 매우 중요합니다 %2520 OAuth 버그.
두번째, 반복되는 키. URL 은 합법적으로 동일한 키를 두 번 이상 전달할 수 있습니다: ?tag=react&tag=typescript&tag=node니다. 많은 순진한 파서들은 이것들을 붕괴시켜서 처음이나 마지막 값만 유지하고 데이터를 조용히 잃어 버립니다. 그것은 잘못된 것입니다 - 반복되는 키는 HTML 양식이 다중 선택 필드를 제출하는 방법과 많은 API 가 배열을 표현하는 방법입니다. 파서는 모든 발생을 자신의 행으로 순서대로 유지하므로 세 개의 태그를 모두 볼 수 있습니다. JSON 으로 쿼리를 복사하면 반복되는 키는 배열이되며 이는 대부분의 코드가 기대하는 모양입니다.
심지어 이것을 사용하기 위해 전체 URL 도 필요하지 않습니다. 쿼리 문자열만 붙여넣기 - color=red&size=42 - 그리고 도구는 스스로 구문 분석합니다. 웹훅 페이로드 또는 누군가가 전달한 추적 링크를 이해하는 가장 빠른 방법입니다.
URL Parser 를 어떻게 사용하나요?
이 도구는 방해가되지 않도록 설계되었습니다. 단일 입력에 URL 을 붙여 넣으면 입력 할 때 실시간으로 구문 분석됩니다 - 누를 버튼이 없습니다. 샘플 링크가 사전로드되어 전체 분석을 즉시 볼 수 있으며 지우기 버튼이 필드를 비 웁니다.
구성표를 입력할 필요가 없습니다. 다음과 같은 bare 호스트를 붙여넣습니다 example.com/pricing 그리고 파서가 앞에 옵니다 https:// 자동으로,그때 작은 메모와 함께 그렇게했다 알려줍니다,그래서 당신은 구성표가 어디에서 왔는지 혼동하지 않습니다. 명시 적 구성표를 붙여 넣기 - http://, ftp://, ssh:// - 그리고 대신 그것을 존중합니다.
출력에는 4 개의 영역이 있습니다. 맨 위에는 정규화된 URL - 미묘한 정규화 차이를 포착하는 데 편리한 복사 버튼이 있는 표준 형식인 browser's 엔진이 생산되었습니다. 그 아래에는 구성품 테이블,부분 당 1 개의 레테르를 붙인 행,각자 자주적으로 베낄 수 있는. 그 때 경로 세그먼트, 인덱스 칩으로 분할되어 다음과 같은 깊은 경로를 갖습니다 /api/v2/users/42/orders 는 한눈에 읽을 수 있다. finally the 쿼리 매개변수 "json" 로 복사;로 디코딩되고 정렬된 테이블 전체 쿼리를 깨끗한 개체로 바꾸는 작업입니다.
모든 것은 기본 URL 엔진을 사용하여 브라우저에서 실행됩니다. 그것은 고의적 인 선택입니다: URL 은 일상적으로 액세스 토큰,세션 ID,서명 된 매개 변수 및 내부 호스트 이름을 포함하고 있으며 그 중 어느 것도 단지 읽기 위해 서버로 보내져서는 안됩니다. 붙여 넣기 한 것이 장치를 떠나지 않으며 도구는 오프라인으로 계속 작동합니다. 그것은 내가 들어가서 전체 툴킷 뒤에있는 동일한 개인 정보 우선 접근 방식입니다 웹 개발자 툴킷 가이드.
URL 파서에 언제 도달합니까?
몇 가지 상황이 내 자신의 작업에서 몇 번이고 나타납니다. 리디렉션 및 콜백 디버깅 가장 큰 것은 OAuth 흐름, 결제 반환 URL, SSO 핸드셰이크입니다. 이 모든 기능은 두 URL을 모두 분해할 때만 표시되는 작은 불일치로 인해 실패합니다. 추적 링크 감사 또 다른: 마케팅 URL 은 종종 기본 페이지 플러스 다스 UTM 및 광고 플랫폼 매개 변수,그리고 테이블로 읽는 것은 300 자 문자열에 눈을 가늘게 뜨고 비트. 당신이 그들을 읽는 것보다 그 링크를 구축하는 경우,the UTM 빌더 는 동일한 워크플로의 나머지 절반입니다.
그럼 있잖아 API 작업 - 클라이언트가 실제로 보낸 쿼리 매개변수를 검사하거나 엔드포인트가 필터를 어떻게 기대하는지 리버스 엔지니어링합니다. 그리고 보안 검토: 이메일이나 로그에 있는 익숙하지 않은 링크는 해당 부분을 구문 분석하여 이해하는 것이 훨씬 안전합니다(호스트가 이를 수행하는 작업) 정말 point at? 저 호스트명은 IP 인가요?) 를 클릭하는 것보다. 파서는 진정한 호스트명을 노출시키고 IP-리터럴 호스트를 플래그하는데,이는 정확히 링크를 신뢰하기 전에 원하는 정보입니다. 나는 이런 종류의 검사 키트를 조립하는 것에 대해 더 많이 썼습니다 API 디버깅 도구 가이드.
구문 분석은 인코딩 및 slugs와 어떤 관련이 있습니까?
URL 파서는 작은 링크 도구 제품군의 한 구석이며,필요한 것이 무엇인지 알면 시간이 절약됩니다. 파싱 읽다 기존 URL을 가져와서 분리합니다. 부호화 문자 수준에서 반대 방향이 수행 - 자신의 퍼센트 인코딩 된 형태로 공간과 특수 문자를 선회 그래서 그들은 URL 내부에 생존, 다시. 당신은 안전하게 쿼리 문자열에 값을 포함해야 할 때, 또는 망가져 하나를 디코딩, 즉 URL 인코더/디코더그리고 파서와 자연스럽게 쌍을 이룹니다: 구조를 보려면 구문 분석하고, 깨진 값을 수정하려면 인코딩합니다.
Slug 세대 세 번째 관련 직업입니다. "더 빠른 빌드 및 견적을 위한 10가지 팁; 그리고 그것을 깨끗하게 바꾸는 것 10-tips-for-faster-builds 경로 세그먼트. 그게 뭐야 Slug 생성기 핸들, 그리고 깔끔한 것을 생산하는 것입니다 path 나중에 파서가 다시 읽는 구성 요소. 파이프 라인으로 생각하십시오: 좋은 경로를 구축하기 위해 slugify,값 URL-안전하게 만들기 위해 인코딩,완료 된 링크를 검사하기 위해 구문 분석. 각 도구는 URL 수명주기의 한 부분을 수행하고 브라우저에서 수행합니다.
IP 주소와 국제화된 도메인은 어떻습니까?
모든 호스트가 깔끔한 것은 아닙니다 example.com. 일부 URL은 원시 IP 주소를 가리키며 파서는 두 형식을 모두 인식합니다. IPv4 리터럴과 같습니다 http://192.168.1.10:3000/ 의 호스트 이름을 가지고 있습니다 192.168.1.10그리고,도구는 도메인이 아닌 IP 로 플래그 - 당신이 링크를 감사하고 의심스러운 링크에서 일반적인 신호 인 명명 된 사이트 또는 베어 주소를 대상으로 여부를 즉시 알고 싶을 때 유용 IPv6 리터럴은 URL 에서 대괄호로 싸여 있습니다,에서와 같이 http://[2001:db8::1]:8080/그리고 괄호는 장식이 아닌 호스트 구문의 일부입니다; 파서는 포트 구분 기호처럼 보이는 콜론을 질식시키는 대신 괄호로 묶인 형태를 올바르게 처리합니다.
국제화된 도메인 이름은 다른 가장자리 케이스입니다. ASCII 문자가 아닌 문자로 작성된 호스트 - 예를 들어 악센트가 있거나 라틴어가 아닌 문자가 있는 도메인 -는 browser's URL 엔진에 의해 Punycode로 변환됩니다 xn-- DNS는 ASCII만 말하기 때문에 실제 요청에 대한 양식입니다. 정규화된 것을 봅니다 href 파서에서 브라우저가 해결할 내용을 정확하게 보여 주며,이는 때때로 자신의 예쁜 유니코드 도메인이 변경되지 않고 이동할 것으로 예상했던 사람들을 놀라게 합니다. 최상위 도메인의 경우 파서는 명명된 호스트의 최종 레이블을 추출하므로 shop.example.co.uk 의 TLD를 보고합니다 uk. 이는 의도적으로 간단한 규칙입니다. 다음과 같은 다중 부분 접미사를 선택하지 않습니다 .co.uk 등록 가능한 도메인으로,그것을 제대로 하려면 큰 이동 데이터 세트인 Public Suffix List 가 필요하기 때문입니다. 빠른 검사를 위해 마지막 레이블은 유용한 신호이며,더 엄격한 어떤 것이든 전용 라이브러리에 도달하게 됩니다.
작업한 예제는 이를 하나로 묶습니다. 결제 제공업체가 반환 URL 을 계속 거부한다고 가정합니다. 등록했습니다 https://app.example.com/checkout/return 그러나 실패한 요청이 표시됩니다 https://app.example.com:443/checkout/return/. 둘 다 구문 분석합니다. 파서는 첫 번째 has host 를 보여줍니다 app.example.com (기본 포트, 경로에 후행 슬래시가 없음) 두 번째 포트에는 호스트가 있습니다 app.example.com 너무 - 하지만 그 길은 /checkout/return/ 슬래시가 뒤따르고 포트가 명시적으로 다음과 같이 작성되었습니다 :443. 눈이 미끄러지는 두 가지 차이점은 둘 다 정확한 일치 확인에 치명적입니다. 일단 별도의 라벨이 붙은 구성 요소로 볼 수 있으면 수정 사항이 분명합니다: 후행 슬래시를 정규화하고 중복 명시적 포트를 삭제합니다.
URL을 읽을 때 흔히 저지르는 실수
반복되는 오류는 이름을 지정할 가치가 있습니다. 조각과 경로 또는 쿼리를 혼동합니다 - 이후의 모든 것 # 조각은 브라우저에서 전적으로 처리되며 서버로 전송되지 않으므로 뒤에 넣은 매개변수입니다 # 백엔드에 도달하지 않습니다. 누락된 포트를 가정하면 포트가 없음을 의미합니다 - 생략된 포트는 구성표를 의미합니다 기본값 (https의 경우 443, http의 경우 80), 파서는 요청이 실제로 어떤 포트에 도달할지 알 수 있도록 명시적으로 만듭니다.
이중 인코딩 무시 - 값이 다음과 같다면 %2520 대신 %20, 두 번 인코딩되었습니다; 구문 분석하고 디코딩된 값에 여전히 백분율 시퀀스가 포함되어 있으면 다시 디코딩합니다. 링크의 보이는 텍스트를 신뢰합니다 - 보이는 텍스트와 실제 텍스트입니다 href 는 완전히 다를 수 있으며,이는 피싱 뒤에있는 전체 메커니즘입니다; 구문 분석은 실제 대상 호스트를 드러냅니다. 그리고 반복되는 쿼리 키를 폐기할 중복으로 처리합니다 - 의미 있는 배열인 경우가 많으며 이를 삭제하면 데이터가 손실됩니다.
자주 묻는 질문
URL의 일부는 무엇입니까?
URL에는 구성표(HTTPS), 선택적 자격 증명(user:pass@), 선택적 포트, 경로(/blog/post)가 있는 호스트(example.com), 선택적 쿼리 문자열(?id=42), 선택적 조각(#section)이 있습니다. 이 파서는 각각을 구분하고 레이블을 지정합니다.
쿼리 문자열을 어떻게 구문 분석합니까?
전체 URL 을 붙여넣고 쿼리 테이블을 읽거나 쿼리 문자열만 자체적으로 붙여넣습니다. 파서는 이를 앰퍼샌드에서 분할하고 퍼센트 인코딩을 디코딩하며 모든 키-값 쌍을 순서대로 나열합니다. tag=a&tag=b 와 같은 반복된 키는 별도의 행으로 유지됩니다.
호스트 이름, 호스트 및 원본의 차이점은 무엇입니까?
호스트 이름은 도메인 또는 IP (example.com) 일뿐입니다. 호스트는 포트가 있을 때 포트를 추가합니다 (example.com:8443). Origin 은 구성표에 호스트를 더한 것입니다 (https://example.com:8443) 및 는 브라우저가 동일 출처 보안 검사에 사용하는 것입니다.
URL에 포트 번호가 없을 때 사용되는 포트는 무엇입니까?
계획이 결정합니다. HTTPS는 기본값이 443, HTTP는 80, SSH는 22, FTP는 21입니다. 이 파서는 유효 포트를 표시하고 기본값으로 표시하므로 요청이 실제로 사용할 포트를 알 수 있습니다.
파서가 백분율로 인코딩된 문자를 디코딩합니까?
네,쿼리 값의 경우. name=John%20Doe 와 같은 매개 변수가 표에서 "John Doe"로 디코딩된 것으로 표시됩니다. 원시 검색 문자열도 그대로 표시되므로 인코딩된 양식과 디코딩된 양식을 비교할 수 있습니다.
https 부분을 입력하지 않고 URL을 구문 분석할 수 있습니까?
네. example.com/pricing과 같은 베어 호스트 또는 경로를 붙여넣는 경우 파서는 자동으로 https://를 앞에 두고 이 구성표를 가정했음을 기록합니다. 해당 가정을 재정의하려면 http:// 또는 ftp://와 같은 체계를 명시적으로 붙여넣습니다.
내 URL이 구문 분석에 실패하는 이유는 무엇입니까?
일반적으로 호스트가 없거나 형식이 잘못되었거나, 체계가 잘못 작성되었거나, 문자열에 URL에서 불법이고 퍼센트 인코딩되지 않은 문자가 포함되어 있습니다. 스페이스, 이스케이프되지 않은 대괄호 또는 스키마 후 누락된 슬래시가 있는지 확인합니다.
토큰이나 세션 ID로 URL을 붙여넣는 것이 안전합니까?
네. 구문 분석은 기본 URL 엔진을 사용하여 브라우저에서 완전히 실행됩니다. 링크는 서버로 전송되지 않고, 기록되지 않으며, 저장되지 않으므로 액세스 토큰, API 키 또는 내부 호스트 이름이 포함된 URL이 장치에 유지됩니다.



