
Handlers.pudu
Pudu74 lines3.4 KB
1/** @Examples.Handlers.Program — delegating handlers, logging, metrics, and event listeners */2module Handlers34import Std.Concurrent.Cancel as Cancel5import Std.Concurrent as Concurrent6import Std.Http.Server.Reply as Reply7import Std.Http.Server.Route as Route8import Std.Http.Server as Server9import Std.Io as Io10import PuduLangHttpClient.Client as Client11import PuduLangHttpClient.Events as Events12import PuduLangHttpClient.Factory.Builder as Builder13import PuduLangHttpClient.Factory as Factory14import PuduLangHttpClient.Handler as Handler15import PuduLangHttpClient.Handlers.Logging as Logging16import PuduLangHttpClient.Handlers.Metrics as Metrics17import PuduLangHttpClient.Handlers.Propagation as Propagation18import PuduLangHttpClient as HttpClient19import PuduLangHttpClient.Request as Request20import PuduLangHttpClient.Response as Response21import PuduLangLog.Configuration as Configuration22import PuduLangLog as Log23import PuduLangLog.Sinks.Console as Console242526fn stamping(request: Request.Request, token: Cancel.Token, next: Handler.Send) -> HttpClient.Outcome[Response.Response] {27 let began = clock()28 let response = next(request.setHeader("x-request-id", "req-" + show(began)), token) ?29 Ok(response.withHeader("x-client-elapsed", show(clock() - began)))30}313233fn serve() -> (Server.Running, Str) {34 let running = match Server.start("127.0.0.1", 0) {35 case Ok(found) => found36 case Err(problem) => panic(show(problem))37 }38 let server = Server.server(&Route.routing(&[Route.get("/whoami", |request: Route.Request| Reply.text(200, match Route.header(&request, "x-correlation-id") {39 case Some(found) => found40 case None => "nobody"41 }))]))42 let _serving = Concurrent.start(fn() -> () { let _ran = Server.run(&server, &running, 0) })43 (running, "http://127.0.0.1:" + show(Server.portOf(&running)) + "/")44}454647fn main() -> Int {48 let (running, base) = serve()49 let logger = Configuration.create().minimumLevel(Log.Information).writeTo(Console.sink(Console.defaults())).createLogger()50 let meter = Metrics.meter()51 let incoming = || [("x-correlation-id", "order-1234")]52 let options = Factory.Options{listeners: Events.listeners().onRequestCompleted(fn(event: Events.RequestCompleted) -> () {53 let _said = Io.writeLine("completed " + event.client + " " + event.uri + " with " + show(event.status))54 }) }55 let factory = match Factory.buildWith(&options, [56 Builder.defaults().observedBy(Logging.observer(logger)).withHandler(Metrics.handler(&meter)),57 Builder.named("api").withBaseAddress(base).withHandler(stamping).withHandler(Propagation.handler(&["x-correlation-id"], incoming))58 ]) {59 case Ok(built) => built60 case Err(invalid) => panic(Factory.explain(&invalid))61 }62 let client = Factory.createClient(&factory, "api")63 let answered = Client.getText(&client, "whoami")64 let response = Client.get(&client, "whoami")65 let stamped = match response {66 case Ok(found) => Response.header(&found, "x-client-elapsed") != None67 case Err(_) => false68 }69 let snapshot = Metrics.snapshot(&meter)70 Factory.dispose(&factory)71 let _stopped = Server.stop(&running)72 if answered == Ok("order-1234") && stamped && snapshot.successful == 2 { 0 } else { 1 }73}74