문서 작업 가이드
인코딩된 쿼리 매개변수를 이중 디코딩 없이 디버깅하는 방법
원시 쿼리 증거를 보존하고 폼 +와 퍼센트 디코딩 경계를 구분한 뒤 중첩 문자열 문법 하나만 점검하고 깨진 매개변수 계층만 다시 만듭니다.
작성 및 검수 SimpleWebUtils게시일: 검토일:
이 작업 흐름을 검증한 방법
개발자 변환 워크벤치로 “반복 tag를 유지하며 URL과 JSON 문자열 디코딩 분리” 샘플 입력을 정확히 재현했습니다. 결과 비교에는 “URL 원본과 쿼리 텍스트 원본을 명시적으로 선택합니다”, “모든 원시·디코딩 항목을 순서대로 비교합니다” 단계를 포함했습니다. 이어서 연결된 테스트 근거에서 “더하기 기호 전체 치환”, “문자열 이스케이프 해제를 URL 디코더로 사용” 조건을 점검했습니다.
반복 tag 순서, “C++ URL”인 q, 두 번째 형식 해제 뒤 두 줄이 된 message, 값 없는 flag와 #results fragment가 각각의 계층을 유지했습니다.
문제 상황
쿼리 값은 URL 파싱, 폼 쿼리 디코딩, 프레임워크 매개변수 API, JSON 파싱, 애플리케이션별 이스케이프 해제를 차례로 거칠 수 있습니다. 전체 URL에 decodeURIComponent나 문자열 이스케이프 해제를 적용하면 보호된 앰퍼샌드가 활성화되고 실제 더하기 기호가 공백이 되며 중복 증거가 사라지거나 중첩 값이 너무 일찍 디코딩될 수 있습니다. 이 절차는 한 요소를 바꾸기 전에 각 계층의 원시 입력과 변환 결과를 기록하고, 어느 파서가 값을 바꿨는지 실제 수신기에서 다시 확인합니다.
이럴 때 사용하세요
- C++, 전화번호, 서명, 검색 값에서 +, %2B, %20을 같은 것으로 처리해 값이 달라질 때
- 반복된 filter, tag, scope, state 키가 백엔드에 하나의 값으로만 도착할 때
- 쿼리 값이 URL 디코딩된 뒤 \n 또는 \uXXXX 같은 JSON 문자열 이스케이프를 포함할 때
- returnUrl, next, redirect, payload 값 안에 인코딩된 앰퍼샌드, 등호, 물음표, 프래그먼트가 있을 때
- 클라이언트와 서버 로그의 값은 다른데 어느 로그도 원본 쿼리 세그먼트를 보존하지 않았을 때
단계
- 1단계
수정하기 전에 정확한 요청 대상을 보존합니다
원본 URL이나 원시 쿼리를 신뢰할 수 있는 로컬 위치에 보관합니다. 공유할 사본에서는 실제 토큰, 인증 코드, 개인정보, 자격 증명을 제거하되 보호된 증거에서는 앰퍼샌드, 등호, 반복 키, 더하기 기호, 퍼센트 바이트, 프래그먼트 구조를 유지합니다.
- 2단계
URL 원본과 쿼리 텍스트 원본을 명시적으로 선택합니다
개발자 변환 워크벤치에서 쿼리 문자열을 엽니다. 전체 요청 URL이면 절대 URL을, ? 뒤의 부분만 있으면 쿼리 텍스트를 선택합니다. URL 원본 모드는 절대 URL을 검증하고 프래그먼트를 제외한 뒤 항목을 분리합니다.
- 3단계
모든 원시·디코딩 항목을 순서대로 비교합니다
보고서를 실행하고 원시 키, 원시 값, 디코딩 키, 디코딩 값, 등호 상태, 빈 세그먼트, 반복 키를 확인합니다. 폼 규칙에서 원시 +는 공백이 되고 %2B는 실제 더하기 기호가 됩니다. 수신 프레임워크를 시험하기 전에는 반복 키를 합치지 않습니다.
- 4단계
중첩 값 하나만 분리합니다
다른 문법이 남아 있는 디코딩 값만 복사합니다. \n 같은 시퀀스가 있는 JSON 문자열 내용이라면 문자열 이스케이프에서 JSON과 이스케이프 해제를 선택해 그 값만 처리합니다. 중첩 URL이라면 바깥 URL을 다시 디코딩하지 말고 해당 값을 별도로 파싱합니다.
- 5단계
한 계층만 수정하고 한 번 인코딩합니다
문제가 확인된 값을 원래 문법에서 수정합니다. 예약 문자가 전송 중 보존되어야 하면 URL 인코더·디코더로 해당 쿼리 구성요소 하나만 처리합니다. 전체 치환이나 읽을 수 있을 때까지 반복 디코딩하는 방식은 원본 계층 증거를 없애므로 피합니다.
- 6단계
다시 파싱하고 실제 수신기를 재현합니다
수정한 구성요소를 바깥 쿼리에 넣고 보고서를 다시 실행해 원시·디코딩 열이 의도한 값과 같은지 확인합니다. 그다음 통제된 환경에서만 요청을 보내 실제 프레임워크가 반복 키, 빈 값, 더하기 기호, 중첩 내용을 어떻게 노출하는지 기록합니다.
예시
반복 tag를 유지하며 URL과 JSON 문자열 디코딩 분리
입력
https://example.com/search?tag=one&tag=two&q=C%2B%2B+URL&message=Line%5CnNext&flag#results출력
tag는 순서가 있는 두 항목으로 유지되고 q는 C++ URL로 디코딩되며 message는 먼저 JSON 문자열 내용 Line\nNext로 URL 디코딩한 뒤 JSON 이스케이프 해제로 두 줄이 됩니다. flag는 등호 없는 항목으로 남고 #results는 쿼리에서 제외됩니다.흔한 실수
전체 URL 디코딩
모든 퍼센트 이스케이프를 한 번에 해제하면 중첩 &, =, ?, #가 바깥 계층에서 활성화될 수 있습니다. 바깥 쿼리를 먼저 파싱하고 선택한 값만 처리합니다.
더하기 기호 전체 치환
원시 +는 보통 폼 쿼리의 공백이고 %2B는 실제 더하기 기호입니다. 전체 치환은 C++, 서명, 전화번호, 불투명 식별자를 손상할 수 있습니다.
문자열 이스케이프 해제를 URL 디코더로 사용
백슬래시 이스케이프와 퍼센트 이스케이프는 다른 문법입니다. 매개변수 계층을 먼저 URL 디코딩하고 실제로 해당 문법이 있을 때만 중첩 JSON·JavaScript 문자열 내용을 해제합니다.
반복 키를 객체 하나로 합치기
객체 변환은 값 하나만 남길 수 있습니다. 수신기의 첫 값, 마지막 값, 목록 동작을 확인할 때까지 순서가 있는 항목을 보존합니다.
운영 매개변수 원문 공유
로컬 처리는 스크린샷이나 다운로드 보고서의 비밀을 제거하지 않습니다. 증거가 신뢰 경계를 나가기 전에 토큰, 개인정보, 인증 코드, 비공개 payload를 가립니다.
자주 묻는 질문
쿼리 매개변수는 몇 번 디코딩해야 하나요?
문서화된 인코딩 계층마다 한 번씩만 디코딩합니다. 바깥 쿼리부터 시작해 결과로 나온 매개변수 하나를 확인하고 해당 값이 다른 파서를 위해 명시적으로 인코딩된 경우에만 중첩 URL이나 문자열 문법을 디코딩합니다.
flag와 empty=를 왜 다르게 표시하나요?
flag에는 등호가 없고 empty=에는 명시적인 빈 값이 있습니다. 프레임워크마다 같은 것으로 보거나 다르게 볼 수 있으므로 보고서는 정책을 정하지 않고 문법을 보존합니다.
쿼리 키가 반복되면 어떤 값이 사용되나요?
URL은 원본 순서를 보존하지만 프레임워크는 첫 값, 마지막 값, 목록, 사용자 정의 동작을 사용할 수 있습니다. 진단 과정에서 값을 합치지 말고 실제 수신기를 시험합니다.
백슬래시 이스케이프에는 JSON과 JavaScript 중 무엇을 선택하나요?
중첩 문자열을 읽을 파서의 문법을 선택합니다. JSON이 더 엄격합니다. JavaScript 모드는 추가 형식을 지원하지만 알 수 없는 형식, 오래된 8진수, 끝의 백슬래시, 잘못된 유니코드는 거부합니다.
로컬 보고서가 성공하면 실제 요청도 성공하나요?
아닙니다. 선택한 규칙으로 제한된 로컬 문법을 처리했다는 뜻일 뿐입니다. 프록시 재작성, 프레임워크 파싱, 서명, 리디렉션, 권한, 네트워크 동작, 대상 안전성은 별도로 시험해야 합니다.
워크벤치가 URL이나 매개변수 값을 외부로 보내나요?
이 변환들은 네트워크 요청을 보내지 않습니다. 분석 데이터에는 선택한 모드와 집계 개수만 포함되며 URL 텍스트, 키, 값, 중첩 payload, 생성 보고서는 포함되지 않습니다.