4. Response 계약¶
4.1 terminator 축(§5.1)¶
| 형태 | 공통 개념명 | 반환 | 실패 조건 |
|---|---|---|---|
| raw | submitRaw() |
RawHttpResponse |
전송 실패만. status는 실패 아님(4xx/5xx도 성공 반환) |
| typed | submit<T>() |
HttpResponse<T> |
전송 실패 + status ≥ 400 + 디코드 실패 |
| 다운로드 | download(sink) |
RawHttpResponse(body 빈 값) |
전송 실패. status는 raw와 동일 취급 |
- typed 제출의 status ≥ 400은
InternalFailure로 보고한다. 현행 계약에서는 이때 응답 body가 노출되지 않는다 — 에러 페이로드가 필요하면submitRaw()를 쓴다(개정 후보 R1). - 완료 값을 동기로 언래핑하는 public terminator는 두지 않는다. typed response의 body만 필요하면 비동기 typed terminator를 완료한 뒤 호출자가 body를 선택한다 (5장).
4.2 응답 타입¶
RawHttpResponse { status: int, headers: map<string,string>, body: string }HttpResponse<T> { status: int, headers, body: T, rawBody: string }- HEAD 응답과 204는 빈 body. typed 경로에서 빈 성공 응답의 body는 언어의 "없음" 값(null 등)이다.
4.3 헤더 표현¶
- 응답 헤더 name 조회는 대소문자 무시와 동등해야 한다. cpp/java/node는
소문자 정규화 map, dotnet은 원 표기 보존 + case-insensitive map
(
OrdinalIgnoreCase) — 둘 다 계약을 충족한다(2026-07-12 R6 승격으로 cpp의 대소문자 구분 map 편차 해소).
4.4 download(sink) 의미론¶
- sink는 push형 chunk 콜백이다(바이트 뷰:
string_view/ReadOnlyMemory<byte>/byte[]/ByteArray/Uint8Array). - 누적 크기에
maxResponseBodySize상한을 적용한다. - 압축 해제를 적용하지 않는다 — 원시 바이트가 그대로 전달된다(8장).
- retry에서 제외된다(sink 재생 불가).
- redirect 추적 중 중간 응답의 body는 sink로 새지 않는다. 최종 응답만 sink로 흐른다.
4.5 typed 디코드¶
- JSON 디코드 실패는
ProtocolError. - node는 prototype-pollution 방어로
__proto__/constructor/prototype키를 제거한다(언어 고유 보안 규칙, 계약 위반 아님).