# ========================================== # 대용량 첨부의 공개 API — /api/public-links/ (11단계 — docs/mail/api-contract.md 4절 "공개 내려받기") # # 두 server 의 location ^~ /api/ 블록 **안에** 넣는다(nginx.conf) — 공개 내려받기 server 는 늘, 포털은 공개 호스트를 따로 두지 않을 때 # (nginx-env.envsh 의 NGINX_PORTAL_SHARE=open). 템플릿이 아니다 — /etc/nginx/snippets/share-api-open.conf 로 그대로 들어간다(Dockerfile). # $backend_upstream 과 limit_conn 의 영역(download_public_*)은 nginx.conf 의 http 단계, @api_* 는 nginx-api-errors.conf. # /api/ 블록의 add_header_inherit off 를 물려받는다 — 응답의 머리글(no-store · noindex · no-referrer · 파일의 CSP 등)은 백엔드가 정한다. # # 대소문자를 가리지 않는다(~*) — 백엔드(Express) 라우팅이 가리지 않아 /api/Public-Links/…/FILES/… 도 받기 처리기에 닿는다(nginx.conf 머리말). # 정규식은 적은 차례로 처음 맞은 것을 쓴다 — 파일 받기를 링크 정보보다 먼저 둔다. # ========================================== # 파일 받기 GET·HEAD /api/public-links/{token}/files/{fileId} — 200 · 206(Range) · 416, 2GB 까지 # - 버퍼링을 끈다: 기본값이면 받는 쪽이 느릴 때 nginx 가 응답을 임시 파일(/tmp/proxy_temp)에 1GB 까지 받아 둔다 — 받는 사람마다. # 백엔드가 보내는 X-Accel-Buffering: no 로도 꺼지지만 그 머리글에 기대지 않는다(실시간 알림과 같다) # - X-Accel-Buffering 을 넘긴다: nginx 계열 외부 리버스 프록시(Nginx Proxy Manager 등)도 이 응답만 버퍼링을 끈다 # - proxy_buffer_size 16k — 머리글 버퍼. 한글 255자 파일 이름이면 응답 머리글이 3.5KB 쯤이다(Content-Disposition 하나가 2.5KB) — 기본 4k 로는 빠듯하다 # 버퍼링을 끈 응답은 본문도 이 크기로 받아 넘긴다(기본 4k 보다 시스템 호출이 적다). proxy_busy_buffers_size 는 nginx 가 함께 맞추라고 하는 값이다 — # 안 적으면 2 × 16k = 32k 가 proxy_buffers(8 × 4k)의 "하나 뺀 합" 28k 를 넘어 설정 검사가 멈춘다. 버퍼링을 끈 location 이라 proxy_buffers 는 쓰이지 않는다 # - 압축하지 않는다(gzip_types 에 application/octet-stream 이 없지만 목록을 넓혀도 이 경로는 그대로) · Range · If-Range 는 손대지 않고 넘긴다 # (nginx 는 프록시한 응답을 스스로 자르지 않는다 — 백엔드의 206 · 416 이 그대로 간다) # - 시간: proxy_read_timeout 은 백엔드에서 "두 번 읽는 사이", send_timeout(기본 60s)은 받는 쪽에 "두 번 쓰는 사이"다 — 느려도 조금씩 # 받아 가면 끊지 않고, 받는 쪽이 60초 동안 하나도 받지 않으면 끊는다(브라우저 · 내려받기 관리자는 Range 로 이어 받는다 — mail/README.md 의 시험) # - 동시 연결: 클라이언트 주소마다 10 · 공개 받기 전체 400 — 넘으면 429 REQ_001 (nginx.conf 의 http 단계 "동시 연결 수") # - 토큰 칸은 [^/]+ 가 아니라 .+ — nginx 는 %2F 를 / 로 풀어 location 을 고르고 백엔드는 한 칸으로 읽는다(지금은 백엔드의 토큰 검사가 그 꼴을 404 로 막지만 기대지 않는다) # - 같은 줄들이 nginx.conf 의 앱 안 받기(/api/messages/{id}/large-files/…) · 휴대폰 앱 받기(/api/app-releases/…/file)에 있다 — 한쪽을 고치면 다른 쪽도 # error_page 를 하나라도 쓰면 위의 것을 물려받지 않아 셋을 다 적는다 location ~* ^/api/public-links/.+/files/ { limit_conn download_public_ip 10; limit_conn download_public_total 400; error_page 413 @api_payload_too_large; error_page 429 @api_too_many_requests; error_page 500 502 503 504 @api_unavailable; proxy_buffering off; proxy_buffer_size 16k; proxy_busy_buffers_size 16k; gzip off; proxy_pass_header X-Accel-Buffering; proxy_pass $backend_upstream; } # 링크 정보 GET /api/public-links/{token}(JSON) 등 — 백엔드로 넘긴다. 공개 내려받기 server 의 /api/ 블록은 404 만 정하므로 여기서 다 적는다 location ~* ^/api/public-links(?:/|$) { error_page 413 @api_payload_too_large; error_page 500 502 503 504 @api_unavailable; proxy_pass $backend_upstream; }