How do I create HTTP responses in EK9 services?

← Web Services · Ref: Q201

Service methods return HTTPResponse, a trait with methods for content, status, headers, and caching. Use dynamic classes to implement it inline.

HTTPRESPONSE TRAIT

HTTPResponse defines these methods:

  content()           the response body
  status()            HTTP status code (200, 404, etc.)
  contentType()       MIME type (application/json, etc.)
  cacheControl()      cache directives
  contentLanguage()   language tag

DYNAMIC IMPLEMENTATION

Create inline with dynamic class syntax:

  <- response as HTTPResponse: () with trait HTTPResponse
    override content()
      <- rtn as String: `{"msg": "ok"}`
    override status() as pure
      <- rtn as Integer: 200
    override contentType() as pure
      <- rtn as String: "application/json"
    ...
    default operator ?

STATUS CODES

Return appropriate HTTP status codes:

  200 for success, 201 for created,
  204 for no content, 404 for not found.

See Q199 for REST GET endpoints. See Q200 for CRUD operators. See Q115 for dynamic classes. See Q106 for traits.

Example

defines module qa.web.httpresponse

  defines service

    Health :/health open

      check() as GET for :/status
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"status": "healthy"}`
          override status() as pure
            <- rtn as Integer: 200
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "no-cache"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

  defines application

    HealthApp
      register Health()

  defines program

    HttpResponseDemo()
      stdout <- Stdout()

      stdout.println("HTTPResponse trait methods:")
      stdout.println("  content() - response body")
      stdout.println("  status() - HTTP status code")
      stdout.println("  contentType() - MIME type")
      stdout.println("  cacheControl() - cache directive")
      stdout.println("  contentLanguage() - language tag")

Common mistakes

E50060 — Stdout does not have a display() method. The correct method is println(). Calling a non-existent method triggers E50060 — method not resolved. See ek9 -h E50060 for details.

Incorrect:

stdout.display("HTTPResponse trait methods:")

Correct:

stdout.println("HTTPResponse trait methods:")
Other ways to ask this
  • How does the HTTPResponse trait work in EK9?
  • How do I set HTTP status codes in EK9 services?
  • How do I return JSON from an EK9 service?

Coming from another language?

Java: JAX-RS Response.ok().entity(body).build() or Spring ResponseEntity. Python: Flask make_response() or return tuple (body, status). Rust: axum IntoResponse trait. Go: w.WriteHeader(status) + w.Write(body). Kotlin: Ktor call.respond(). EK9: dynamic class implementing HTTPResponse trait inline.

Keywords: define, content, closure, dynamic, anonymous, trait, http, status, rest, service, response, delegate, capture, cache