
Request.pudu
Pudu121 lines5.1 KB
1/** @HttpClient.Request.Module — what a client sends, built before anything is sent */2module PuduLangHttpClient.Request34import Std.Http as Http5import PuduLangHttpClient.Content as Content6import PuduLangHttpClient.Domain.Headers as Headers7import PuduLangHttpClient.Domain.Version as Version8import PuduLangHttpClient.Options as Options910/** @HttpClient.Request.Receiver — takes each piece of a streamed body; `false` stops reading */11export type Receiver = fn(Bytes) -> Bool1213/** @HttpClient.Request.Request — a method, an address, headers, an optional body, and options */14export type Request = {15 method: Http.Method,16 uri: Str,17 version: Http.Version,18 versionPolicy: Version.Policy,19 headers: Array[(Str, Str)],20 content: Option[Content.Content],21 options: Options.Options,22 receiver: Option[Receiver]23}242526export fn create(method: Http.Method, uri: Str) -> Request {27 Request {28 method: method,29 uri: uri,30 version: Http.Http11,31 versionPolicy: Version.OrLower,32 headers: [],33 content: None,34 options: Options.empty(),35 receiver: None36 }37}383940export fn get(uri: Str) -> Request { create(Http.Get, uri) }414243export fn head(uri: Str) -> Request { create(Http.Head, uri) }444546export fn delete(uri: Str) -> Request { create(Http.Delete, uri) }474849export fn post(uri: Str, content: Content.Content) -> Request { Request{..create(Http.Post, uri), content: Some(content)} }505152export fn put(uri: Str, content: Content.Content) -> Request { Request{..create(Http.Put, uri), content: Some(content)} }535455export fn patch(uri: Str, content: Content.Content) -> Request { Request{..create(Http.Patch, uri), content: Some(content)} }565758export fn header(request: &Request, name: Str) -> Option[Str] {59 match Headers.get(&request.headers, name) {60 case Some(found) => Some(found)61 case None => {62 let content = request.content ?63 Headers.get(&content.headers, name)64 }65 }66}676869export fn option[T](request: &Request, name: &Options.Key[T]) -> Option[T] { Options.get(&request.options, name) }7071/** @HttpClient.Request.Shaping — a request changed one decision at a time */72export trait Shaping {73 74 fn withHeader(self: &Self, name: Str, value: Str) -> Self75 76 fn setHeader(self: &Self, name: Str, value: Str) -> Self77 78 fn removeHeader(self: &Self, name: Str) -> Self79 80 fn withContent(self: &Self, content: Content.Content) -> Self81 82 fn withVersion(self: &Self, version: Http.Version, policy: Version.Policy) -> Self83 84 fn withOption[T](self: &Self, name: &Options.Key[T], value: T) -> Self85 86 fn withReceiver(self: &Self, receiver: Receiver) -> Self87 88 fn withBearer(self: &Self, token: Str) -> Self89 90 fn accepting(self: &Self, mediaType: Str) -> Self91}9293impl Shaping for Request {94 95 fn withHeader(self: &Self, name: Str, value: Str) -> Self { Request{..*self, headers: Headers.add(&self.headers, name, value)} }9697 98 fn setHeader(self: &Self, name: Str, value: Str) -> Self { Request{..*self, headers: Headers.set(&self.headers, name, value)} }99100 101 fn removeHeader(self: &Self, name: Str) -> Self { Request{..*self, headers: Headers.remove(&self.headers, name)} }102103 104 fn withContent(self: &Self, content: Content.Content) -> Self { Request{..*self, content: Some(content)} }105106 107 fn withVersion(self: &Self, version: Http.Version, policy: Version.Policy) -> Self { Request{..*self, version: version, versionPolicy: policy} }108109 110 fn withOption[T](self: &Self, name: &Options.Key[T], value: T) -> Self { Request{..*self, options: Options.set(&self.options, name, value)} }111112 113 fn withReceiver(self: &Self, receiver: Receiver) -> Self { Request{..*self, receiver: Some(receiver)} }114115 116 fn withBearer(self: &Self, token: Str) -> Self { self.setHeader("authorization", Http.bearerAuth(token)) }117118 119 fn accepting(self: &Self, mediaType: Str) -> Self { self.withHeader("accept", mediaType) }120}121