Skip to content
isdnetworks
Go back

클라이언트가 인코딩해 줘서 되던 것

저장소에 파일 이름이 퍼센트 인코딩 문자열 그대로 들어가 있었다.

%EC%83%81%ED%92%88%EC%9D%B4%EB%AF%B8%EC%A7%801.jpg

Table of contents

Open Table of contents

증상 — 리터럴로 들어간 키

한글 파일명이 UTF-8 바이트를 감싼 형태로 리터럴 저장돼 있었다.

원래 한글이었어야 할 이름이 % 로 감싼 문자열 자체로 키가 된 상태였다. 이 상태면 정상적인 URL 요청으로는 그 파일에 못 닿을 것으로 보였다.

검증 — 세 형태로 받아 봤다

curl 로 세 가지 형태를 다 돌려 봤다.

curl -I 'https://.../%EC%83%81%ED%92%88%EC%9D%B4%EB%AF%B8%EC%A7%801.jpg'
403

%EC 로 시작하는 그대로 보내면 거부됐다.

curl -I 'https://.../%25EC%2583%2581%25ED%2592%2588%25EC%259D%25B4%25EB%25AF%25B8%25EC%25A7%25801.jpg'
200

%25EC 로 한 겹 더 씌우니 열렸다.

curl -I 'https://.../상품이미지1.jpg'
403

원문 한글도 거부됐다.

하나만 돌렸으면 403 을 보고 깨졌다로 끝냈을 것이다. 세 개를 대조하니 어느 형태가 맞는지가 그 자리에서 나왔다.

원인 — 이중 인코딩이라야 닿는 키

저장소가 요청 경로를 한 번 디코드해서 키와 맞춘다.

요청  %25EB...
  ↓ 저장소가 1회 디코드
키    %EB...        ← 실제 저장된 이름

키 자체가 이미 %EC 형태이니 보낼 때 한 번 더 감싸야 그 값이 나온다.

이론상으로는 일반적인 요청이 전부 실패해야 하는 상황이었다. 그런데 운영에서는 이미지가 잘 나오고 있었다.

결과 — 클라이언트가 인코딩했다

소비하는 클라이언트가 URL 경로를 자동으로 한 번 인코드하고 있었다.

DB 값     %EB...
  ↓ 클라이언트가 1회 인코드
요청      %25EB...
  ↓ 저장소가 1회 디코드
키        %EB...     ← 맞음

인코드와 디코드가 상쇄되어 항등이 된다.

그러면 인코딩 형태와 무관하게 DB 값과 실제 키가 같기만 하면 성공한다. 형태가 이상한 것과 동작이 깨진 것은 별개였다.

조치 — 저장소를 건드리지 않기

이것을 알기 전과 후가 달랐다.

[전]  저장소 객체 수만 건을 한글로 rename + DB도 수정
[후]  DB를 실제 키에 맞추기만 하면 됨

저장소 객체 수만 건의 rename 이 없어졌다.

앞의 것은 위험하고 오래 걸리는 작업이고 뒤의 것은 조회와 정합 확인으로 끝난다.

주의 — 기대고 있는 조건

다만 이 성립이 클라이언트 쪽 조건 하나에 기대고 있었다.

[웹 클라이언트]  자동 인코드 함  →  됨
[명령줄 도구]    안 함           →  깨짐

클라이언트가 유효한 퍼센트 문자를 한 번 더 인코드해 준다는 조건이다.

curl 처럼 직접 접근하는 경로에서는 그대로 깨진다. 그래서 지금 정상인 것과 구조가 건전한 것을 갈라서 적었다.

근본 정상화는 별도 과제로 남겼다.

저장소 수만 건 rename
+ 전 소비처 호환 재검증

이번 작업으로 묶기에는 너무 크고 당장 필요한 것은 DB 정합이며 그것만으로 운영이 돈다.

검증 도구로 403 이 나와도 실패로 단정하지 않는 습관도 남았다. 그 도구가 자동 인코드를 하는지에 따라 결과가 달라지므로 한 번의 실패는 원인을 가르지 못한다.

정리


Share this post on:

Previous Post
한 경로에만 붙은 가드
Next Post
복제 구성을 장비와 같이 적었다