http1/http1.bend checks
raw source on the hub · import 0x64e1b9e0466cf913fa57e70aeb11c176/http1/http1.bend as Http1
9 imports
import Base import ./bytes.bend as B import ../http/text.bend as T import ../http/method.bend as M import ../http/status.bend as S import ../http/headers.bend as H import ../http/request.bend as Req import ../http/response.bend as Res import ../utf8/utf8.bend as U
Types
type Err source · line 16 · raw
Data
why a request was refused
BadLineErr
BadVersionErr
BadHeaderErr
ObsFoldErr
BadLengthErr
BadHostErr
UnsupportedErr
HeadTooLargeErr
BodyTooLargeErr
type Split source · line 44 · raw
Data
the head, cut into lines at CRLF, up to the empty line
Lines@lines:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes> -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Split
SMoreSplit
SBad@err:Err -> Split
type Version source · line 125 · raw
Data
HTTP/1.1, HTTP/1.0, some other HTTP/x.y, or not a version
V11Version
V10Version
VOtherVersion
VNoneVersion
type Line source · line 153 · raw
Data
Line@method:0x64e1b9e0466cf913fa57e70aeb11c176/http/method.Method -> @target:String -> @v:Version -> Line
LBad@err:Err -> Line
type NV source · line 179 · raw
Data
a header line cut at its colon
NV@name:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> NV
type Field source · line 182 · raw
Data
Field@h:0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header -> Field
FBad@err:Err -> Field
type CL source · line 237 · raw
Data
what the headers say about the message, gathered in one pass
NoLenCL
Len@n:Nat -> CL
LenBadCL
type Frame source · line 242 · raw
Data
Frame@cl:CL -> @te:Bool -> @hosts:U32 -> @close:Bool -> @keep:Bool -> Frame
type HKind source · line 313 · raw
Data
KLenHKind
KTeHKind
KHostHKind
KConnHKind
KOtherHKind
type Scanned source · line 346 · raw
Data
Scanned@hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @fr:Frame -> Scanned
type Fields source · line 359 · raw
Data
FOk@hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> Fields
FErr@err:Err -> Fields
type Took source · line 379 · raw
Data
Took@body:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Took
ShortTook
type Parsed source · line 394 · raw
Data
a request read off the wire: the request, whether to close the connection after answering it, and the bytes after it (the next request, pipelined)
Parsed@req:0x64e1b9e0466cf913fa57e70aeb11c176/http/request.Request -> @close:Bool -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Parsed
MoreParsed
Bad@err:Err -> Parsed
type RParsed source · line 547 · raw
Data
a response read off the wire (for clients, and to test write)
RParsed@code:U32 -> @hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @body:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> RParsed
RMoreRParsed
RBad@err:Err -> RParsed
Definitions
def status source · line 27 · raw
@e:Err -> 0x64e1b9e0466cf913fa57e70aeb11c176/http/status.Status
def split.go source · line 51 · raw
@buf:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @line:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @lines:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes> -> @+n:U32 -> @+max:U32 -> @over:Bool -> Split
line is the current line reversed, lines the ones before, reversed; n counts the bytes so far, and over is n past the limit
def split_sp.go source · line 75 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @cur:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @acc:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes> -> List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes>
def latin1.go source · line 84 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @acc:String -> String
def latin1 source · line 93 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> String
bytes as text, one char per byte: header text is ASCII, and any other byte (obs-text) is kept as the char of that value
def bytes.char source · line 96 · raw
@small:Bool -> @+x:U32 -> @out:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes
def bytes.go source · line 103 · raw
@s:String -> @out:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes
def to_bytes source · line 112 · raw
@s:String -> 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes
text as bytes, the inverse of latin1 for chars below 256; a larger char is written as UTF-8
def same_bytes source · line 115 · raw
@a:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @b:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @ok:Bool -> Bool
def http_like source · line 132 · raw
@v:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Bool
HTTP/d.d
def version.go source · line 139 · raw
@v11:Bool -> @v10:Bool -> @like:Bool -> Version
def version source · line 150 · raw
@+v:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Version
def line.parts source · line 157 · raw
@ok:Bool -> @m:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @t:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @v:Version -> Line
def request_line source · line 168 · raw
@parts:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes> -> Line
def cut_colon.go source · line 186 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @name:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Maybe<&2, NV>
def trim source · line 195 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes
def field.make source · line 198 · raw
@ok:Bool -> @n:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @v:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Field
def field.value source · line 205 · raw
@+n:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+v:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Field
def field.pair source · line 208 · raw
@p:NV -> Field
def field.of source · line 213 · raw
@m:Maybe<&2, NV> -> Field
def field.fold source · line 220 · raw
@folded:Bool -> @l:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Field
def field source · line 229 · raw
@+l:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Field
name ":" OWS value OWS; a line that starts with white space continues the one before (obs-fold), which a server must refuse or rewrite
def nat_le.pick source · line 245 · raw
@le:Bool -> @+a:Nat -> @+b:Nat -> Nat
def cl_digits.end source · line 252 · raw
@ok:Bool -> @+n:Nat -> Maybe<&2, Nat>
def cl_digits.go source · line 261 · raw
@s:String -> @+acc:Nat -> @ok:Bool -> @any:Bool -> Maybe<&2, Nat>
a Content-Length's digits, held at 2^32 - 1 once past it (any body that long is over the limit anyway); None unless all digits and at least one
def cl_merge.eq source · line 268 · raw
@same:Bool -> @+n:Nat -> CL
def cl_merge source · line 276 · raw
@cl:CL -> @m:Maybe<&2, Nat> -> CL
two Content-Lengths must agree (RFC 9112 §6.3)
def lower source · line 285 · raw
@+b:U32 -> U32
def tok.same source · line 288 · raw
@a:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @b:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @ok:Bool -> Bool
def tok.is source · line 297 · raw
@a:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @b:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Bool
def tok.go source · line 300 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @cur:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+want:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @found:Bool -> Bool
def has_token source · line 310 · raw
@v:String -> @want:String -> Bool
whether a comma list like "keep-alive, Upgrade" holds a token
def kind.pick source · line 320 · raw
@hit:Bool -> @k:HKind -> @rest:HKind -> HKind
def kind source · line 327 · raw
@+n:String -> HKind
def frame.step source · line 333 · raw
@k:HKind -> @fr:Frame -> @+v:String -> Frame
def scan source · line 349 · raw
@hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @fr:Frame -> @acc:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> Scanned
def fields.add source · line 363 · raw
@acc:Fields -> @f:Field -> Fields
def fields source · line 372 · raw
@ls:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes> -> @acc:Fields -> Fields
def take source · line 383 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @n:Nat -> @acc:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Took
def req.body source · line 399 · raw
@t:Took -> @m:0x64e1b9e0466cf913fa57e70aeb11c176/http/method.Method -> @target:String -> @hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @close:Bool -> Parsed
def req.len.fits source · line 406 · raw
@ok:Bool -> @n:Nat -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @m:0x64e1b9e0466cf913fa57e70aeb11c176/http/method.Method -> @target:String -> @hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @close:Bool -> Parsed
def req.len source · line 413 · raw
@cl:CL -> @+max:Nat -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @m:0x64e1b9e0466cf913fa57e70aeb11c176/http/method.Method -> @target:String -> @hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @close:Bool -> Parsed
def hosts_ok source · line 422 · raw
@v:Version -> @+h:U32 -> Bool
def close_of source · line 429 · raw
@v:Version -> @+c:Bool -> @+k:Bool -> Bool
def req.check source · line 436 · raw
@te:Bool -> @hosts:Bool -> @cl:CL -> @close:Bool -> @+max:Nat -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @m:0x64e1b9e0466cf913fa57e70aeb11c176/http/method.Method -> @target:String -> @hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> Parsed
def req.frame source · line 445 · raw
@s:Scanned -> @m:0x64e1b9e0466cf913fa57e70aeb11c176/http/method.Method -> @target:String -> @+v:Version -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+max:Nat -> Parsed
def req.fields source · line 450 · raw
@f:Fields -> @m:0x64e1b9e0466cf913fa57e70aeb11c176/http/method.Method -> @target:String -> @+v:Version -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+max:Nat -> Parsed
def req.line source · line 457 · raw
@l:Line -> @hl:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes> -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+max:Nat -> Parsed
def req.lines source · line 464 · raw
@s:Split -> @+max:Nat -> Parsed
def parse source · line 477 · raw
@buf:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+max_head:U32 -> @+max_body:U32 -> Parsed
a request from the bytes received so far: Parsed, More when it is not all here yet, or Bad with why
def count source · line 483 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+n:U32 -> U32
def framing source · line 490 · raw
@+n:String -> Bool
def unsafe.char source · line 493 · raw
@+x:U32 -> Bool
def unsafe source · line 498 · raw
@s:String -> @bad:Bool -> Bool
a CR, LF or NUL: in a header a handler set, it would split the response (RFC 9110 §5.5)
def heads.keep source · line 505 · raw
@drop:Bool -> @n:String -> @v:String -> @out:String -> String
def heads source · line 514 · raw
@hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @out:String -> String
the header lines, reversed onto out; the framing ones are the writer's, and one with a CR, LF or NUL is dropped
def closing source · line 522 · raw
@close:Bool -> String
an HTTP/1.0 client keeps the connection only when told (RFC 9112 §9.3)
def head_bytes source · line 533 · raw
@s:String -> 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes
to_bytes for the writer alone: the compiler decides once per def whether it takes its argument or only reads it, and has_token reads a header value it keeps, while the writer hands over a String it is done with; one def for both would share Strings
def write.go source · line 536 · raw
@+c:U32 -> @hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> @+body:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @close:Bool -> 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes
def write source · line 541 · raw
@r:0x64e1b9e0466cf913fa57e70aeb11c176/http/response.Response -> @close:Bool -> 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes
a response on the wire: status line, headers, Content-Length, and Connection: close when the server will close after it, else keep-alive
def digit3.go source · line 552 · raw
@ok:Bool -> @+n:U32 -> Maybe<&2, U32>
def digit3 source · line 559 · raw
@+a:U32 -> @+b:U32 -> @+c:U32 -> Maybe<&2, U32>
def status_line.ok source · line 562 · raw
@ok:Bool -> @m:Maybe<&2, U32> -> Maybe<&2, U32>
def status_line source · line 570 · raw
@bs:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> Maybe<&2, U32>
HTTP/d.d SP ddd SP reason
def res.body source · line 577 · raw
@t:Took -> @+code:U32 -> @hs:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http/headers.Header> -> RParsed
def res.frame source · line 584 · raw
@s:Scanned -> @+code:U32 -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> RParsed
def res.fields source · line 595 · raw
@f:Fields -> @+code:U32 -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> RParsed
def res.line source · line 602 · raw
@m:Maybe<&2, U32> -> @hl:List<&2, 0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes> -> @rest:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> RParsed
def res.lines source · line 609 · raw
@s:Split -> RParsed
def parse_response source · line 621 · raw
@buf:0x64e1b9e0466cf913fa57e70aeb11c176/http1/bytes.Bytes -> @+max_head:U32 -> RParsed
a response from bytes; with no Content-Length the body runs to the end