http — HTTP/1.1 요청 파서
요청 바이트열을 받아 각 필드가 어디서 시작해 몇 바이트인지 답한다(RFC 9112). 자르지 않는다 — 자르는 것은 부르는 쪽이 subslice 로 한다. 모든 실패는 0 이다. 0 은 정당한 자리가 될 수 없다 — 요청은 최소 GET / HTTP/1.1␍␊␍␊ 라 어떤 필드도 0 에서 시작하지 않는다.
무엇을 약속하고 무엇을 하지 않나
Transfer-Encoding: chunked)을 짓지 않았다 — 그 헤더를 찾아 주기만 하므로 부르는 쪽이 거절해야 한다. 트레일러 · 여러 줄 헤더(obs-fold) · URL 퍼센트 해체 · HTTP/2 가 없다. HTTP/1.0 을 받지 않는다 — 지속 연결 규칙이 다르고 그것을 짓지 않았다.let t u64 be http.target_off b .
let n u64 be http.target_len b .
guard gt n 0 . else return 0 .
let target slice u8 . be subslice b t (add t n) .| op | 하는 일 |
|---|---|
method_get · method_head · method_post · method_put · method_delete | 메서드 코드(1 … 5) |
method_code | 요청 줄의 메서드 → 코드. 0 = 모름 |
line_next · line_len | 다음 줄의 자리 · 이 줄의 내용 길이(CRLF 제외) |
target_off · target_len | 요청 대상의 자리 · 길이 |
version_ok | HTTP/1.1 인가 |
headers_off · header_next | 첫 헤더 · 다음 헤더(빈 줄이면 0) |
name_len · value_off · value_len | 헤더 이름 길이 · 값 자리 · 값 길이 |
name_eq | 이 헤더의 이름이 그것인가(대소문자 안 가림) |
header_find · header_find_len | 그 이름의 값 자리 · 길이. 중복이면 0 |
content_length | option u64 — 없으면 some 0, 성하지 않으면 none |
body_off | 몸통이 시작하는 자리 |
표 50.1 — http 의 op
이 모듈의 알맹이는 거절이다. 파서는 받아들이는 것보다 거절하는 것으로 정의된다. HTTP 에서 잘못 받아들이는 자리에는 이름이 있다 — 요청 밀반입(request smuggling). 앞단(프록시)과 뒷단(서버)이 같은 바이트를 다르게 읽으면 하나가 본 요청을 다른 하나는 못 본다.
| 거절하는 것 | 왜 |
|---|---|
맨 LF 를 줄 끝으로 | 앞단이 CRLF 만 인정하면 경계가 갈린다 |
이름과 콜론 사이 공백(Host : x) | RFC 9112 §5.1 이 거절을 요구한다 |
Content-Length 가 둘 | 값이 같아도 거절한다 |
Content-Length: 5, 5 · +5 · 빈 값 | 숫자만 받는다 — 그 관용이 밀반입이다 |
HTTP/1.0 | 지속 연결 규칙이 다른데 짓지 않았다 |
같은 헤더가 둘(header_find) | 합쳐도 되는지는 헤더마다 다르고 그 표를 짓지 않았다 — 모르면 거절 |
빈 대상(GET HTTP/1.1) · 끝나지 않은 헤더(빈 줄 없음) | — |
표 50.2 — http 가 거절하는 것
content_length 가 option 인 이유. “없다” 와 “틀렸다” 는 다른 답이다. 없으면 some 0(몸통이 없는 정상 요청), 성하지 않으면 none(연결을 끊어야 할 일). 한 값으로 두면 둘이 섞이고, 섞이는 자리가 곧 공격 자리다.
이 모듈이 처리기 결함을 하나 잡았다. 처음에 input b str . 로 썼다. --check 는 통과했는데 21 op 중 16 이 느린 해석 경로로 떨어졌다(약 80 배). str 은 빌트인이 아니라 strings 의 지역 별칭이었고, 검사기는 그 이름을 통과시켰지만 타입 붙은 하강은 뜻을 몰랐다. 답은 맞으므로 시험이 영원히 보지 못하는 조용한 80 배다. 이제 그런 이름을 시그니처에 쓰면 W-NOT-YET 경고가 나온다. 검사가 통과하는 것과 빠른 것은 다른 일이고, --why-slow 를 보지 않았으면 이 파일은 그대로 실렸을 것이다.
확인하는 것 — RFC 9112 예제(정상 8), 거절 9 건, VM·네이티브 일치, 느린 경로로 떨어지는 op 0 개.