httpconn
nimony/lib/std/http/httpconn.nim
func dollar`.ChunkState(e: ChunkState): stringtype HttpConn = object sock: Socket tags: ref HttpTags.Obj not nil scan: HeadScanner chunk: ChunkState chunkLeft: int64
proc initHttpConn(fd: int32; deadline: Deadline; tags: ref HttpTags.Obj not nil): HttpConnfdmust already be non-blocking. The deadline has no default: a connection with no budget is one a quiet peer can hold forever.proc fd(c: HttpConn): int32proc buffered(c: HttpConn): int64Bytes read but not yet consumed — a pipelined request, or the start of a body that arrived with its head.
proc readRequest(c: var HttpConn; m: var HttpMsg; dl: Deadline)The next request head on this connection.
mmust be empty;resetit between requests to reuse its buffer, which is the keep-alive path.proc readResponse(c: var HttpConn; m: var HttpMsg; dl: Deadline)The next response head — the client side of the same loop.
proc isChunked(m: HttpMsg): boolWhether the body is chunk-framed. The parser resolves a known
Transfer-Encodingto a tag, so this is an integer compare.proc bodyLength(m: HttpMsg): int64Declared body length, or
-1when there is none or it is chunked.proc beginBody(c: var HttpConn)Arm the chunk reader for a new body. Call after reading a head whose
isChunkedis true, before the firstreadChunked.proc readChunked(c: var HttpConn; dest: var openArray; dl: Deadline): int64The next piece of a chunk-framed body: the bytes copied, or
0once the body has ended.0means the whole body is over — the zero chunk and its trailers have been consumed and the connection is positioned at whatever follows, so it can be reused. It never means "nothing right now"; the loop keeps reading until it has either bytes or the end.SyntaxErrorfor framing the peer got wrong,EndOfStreamErrorfor a body it stopped sending. Those were one-1before, and they are not the same thing: one is a peer to answer 400, the other a connection to drop.proc readBody(c: var HttpConn; dest: var openArray; dl: Deadline): int64Fills
destwith body bytes, starting with whatever already arrived behind the head. The bytes copied — fewer than asked for only if the peer stopped, which the caller detects by comparing againstcontentLength.Only for
Content-Lengthbodies. AskisChunkedfirst and usereadChunkedif it says so: guessing the framing is how two hops come to disagree about where a message ends. Nothing about it is HTTP, so it isSocket.read— the caller stops atcontentLengthbytes.proc sendHead(c: var HttpConn; m: HttpMsg; dl: Deadline)Serialize
m's head into the connection's write buffer and send it.headLensizes the buffer exactly, so this never writes, fails and retries.ValueErrorfor a message with no head to write — one that was never built, or moved from. ABugErroris what it says:headLenandwriteHeaddisagreed about the same tree.proc sendBody(c: var HttpConn; body: openArray; dl: Deadline)Send a body already in memory. Nothing is copied.
proc sendChunk(c: var HttpConn; data: openArray; dl: Deadline)One chunk. An empty
datais not written: a zero-length chunk is the end-of-body marker, so sending one here would end the body early.endChunksis how a body is ended.proc endChunks(c: var HttpConn; dl: Deadline)The zero chunk and the empty trailer section that end a chunked body.
proc respond(c: var HttpConn; status: int64; body: openArray; dl: Deadline)A complete response: status,
Content-Length,Connection, and the body. The length is always sent — a response whose end the peer has to infer from a close is a response that cannot be followed by another.proc renew(c: var HttpConn; deadline: Deadline)Start the next request's budget. A keep-alive connection serves many requests and each gets its own, or the first one would spend the whole connection's allowance on behalf of all of them.
proc close(c: var HttpConn)Cancel anything still in flight and close the fd. Must run on the thread that submitted those ops — the ring's slot arenas are per-lane, so a connection belongs to its lane for life.