Repository navigation
Getting Started
Install Pudu 0.1.3 or later, then create a project and add the package:
pudu init my-app
cd my-app
pudu install @chrismichaelps/pudu-lang-httpclient@0.1.0A factory holds the configuration of every client a program uses. You describe each client with a
builder — Builder.defaults() for what every client shares, Builder.named(name) for one client —
and build the factory once at startup. Factory.createClient hands back a cheap client over that
name's current handler pipeline. Every request answers an Outcome, which is Result with the
error side fixed to Failure:
module Ex01First
import Std.Concurrent as Concurrent
import Std.Http.Server as Server
import Std.Http.Server.Reply as Reply
import Std.Http.Server.Route as Route
import Std.Io as Io
import PuduLangHttpClient as HttpClient
import PuduLangHttpClient.Client as Client
import PuduLangHttpClient.Factory as Factory
import PuduLangHttpClient.Factory.Builder as Builder
fn serve() -> (Server.Running, Str) {
let running = match Server.start("127.0.0.1", 0) {
case Ok(found) => found
case Err(problem) => panic(show(problem))
}
let server = Server.server(&Route.routing(&[Route.get("/greeting", |_request: Route.Request| Reply.text(200, "hello"))]))
let _serving = Concurrent.start(fn() -> () { let _ran = Server.run(&server, &running, 0) })
(running, "http://127.0.0.1:" + show(Server.portOf(&running)) + "/")
}
export fn main() -> Int {
let (running, base) = serve()
let factory = match Factory.build([
Builder.defaults().withDefaultHeader("user-agent", "first/1.0"),
Builder.named("greeter").withBaseAddress(base).withTimeout(5000)
]) {
case Ok(built) => built
case Err(invalid) => panic(Factory.explain(&invalid))
}
let greeting = Client.getText(&Factory.createClient(&factory, "greeter"), "greeting")
let missing = Client.getText(&Factory.createClient(&factory, "greeter"), "nowhere")
let _first = Io.writeLine(show(greeting))
let _second = Io.writeLine(match missing {
case Ok(text) => text
case Err(failure) => HttpClient.describe(&failure)
})
Factory.dispose(&factory)
let _stopped = Server.stop(&running)
if greeting == Ok("hello") && missing == Err(HttpClient.Unsuccessful(404, "Not Found")) { 0 } else { 1 }
}
Check it and run it:
pudu check src/Ex01First.pudu
pudu run src/Ex01First.puduOutput:
Ok("hello")
The response status 404 (Not Found) does not indicate success.
Factory.build takes every builder as one flat array and answers either the factory or every
problem it found, which Factory.explain puts in one sentence. Client.getText answers the body of
a successful response; a status outside 2xx becomes Unsuccessful with its code and reason, and
HttpClient.describe renders any failure in one sentence. Factory.dispose closes the connections
the factory's pipelines hold.
Make clients where they are needed: a client is a value over the name's pipeline, and the factory renews pipelines underneath it.