
Writer.pudu
Pudu51 lines2.1 KB
1/** @Transport.Writer.Module — a request written as the bytes that go on the wire */2module PuduLangHttpClient.Transport.Writer34import Std.Bytes as ByteSeq5import Std.Http as Http6import PuduLangHttpClient.Domain.Headers as Headers7import PuduLangHttpClient.Domain.Uri as Uri8import PuduLangHttpClient.Request as Request910/** @Transport.Writer.Form — how the request line names its target */11export type Form = OriginForm | AbsoluteForm121314const CRLF: Str = "\r\n"1516171819export fn render(request: &Request.Request, version: &Http.Version, endpoint: &Uri.Endpoint, form: &Form, extra: &Array[(Str, Str)]) -> Bytes {20 let target = match form {21 case OriginForm => Uri.target(request.uri)22 case AbsoluteForm => Uri.withoutFragment(request.uri)23 }24 var head = Http.methodName(&request.method) + " " + target + " " + Http.versionName(version) + CRLF25 if !Headers.has(&request.headers, "host") { head = head + "host: " + Uri.authority(endpoint) + CRLF }26 for pair in request.headers {27 if pair[0].toLower() != "content-length" { head = head + pair[0] + ": " + pair[1] + CRLF }28 }29 let body = match request.content {30 case Some(content) => {31 for pair in content.headers {32 if pair[0].toLower() != "content-length" { head = head + pair[0] + ": " + pair[1] + CRLF }33 }34 content.payload35 }36 case None => ByteSeq.empty()37 }38 let framed = Headers.has(&request.headers, "transfer-encoding")39 let streamed = match request.content {40 case Some(content) => content.stream != None41 case None => false42 }43 if streamed && !framed {44 head = head + "transfer-encoding: chunked" + CRLF45 } else if !framed && (!body.isEmpty() || request.content != None || Http.expectsBody(&request.method)) {46 head = head + "content-length: " + show(body.length()) + CRLF47 }48 for pair in *extra { head = head + pair[0] + ": " + pair[1] + CRLF }49 (head + CRLF).toBytes().concat(body)50}51