Why must every service method return HTTPResponse?

← Web Services · Ref: Q659

Every service method and operator must return HTTPResponse. The response encapsulates the HTTP status code, content body, content type, cache control, and language.

HTTPRESPONSE TRAIT

The HTTPResponse trait defines the contract:

  status() — HTTP status code (200, 201, 404, etc.)
  content() — response body as String
  contentType() — MIME type (application/json, text/html, etc.)
  cacheControl() — caching directives
  contentLanguage() — response language

DYNAMIC CLASS PATTERN

Create responses with anonymous dynamic classes:

  <- response as HTTPResponse: () with trait HTTPResponse
    override content()
      <- rtn as String: "response body"
    override status() as pure
      <- rtn as Integer: 200
    ...

WHY REQUIRED

The web server infrastructure needs standardised response data. Without HTTPResponse, the server cannot send status codes, headers, or content back to clients.

See Q201 for HTTP response details. See Q657 for URI mapping. See Q200 for CRUD operators.

Example

defines module qa.webdeep.returntype

  defines service

    <?-
      Service with methods that correctly return HTTPResponse.
      Every method must satisfy the HTTPResponse trait contract.
    -?>
    Health :/health open

      // GET /health/status — returns 200 with JSON body
      healthCheck() 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 ?

      // GET /health/version — returns version info
      version() as GET for :/version
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"version": "1.0.0"}`
          override status() as pure
            <- rtn as Integer: 200
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "max-age=3600"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

  defines application

    HealthApp
      register Health()

  defines program

    ServiceReturnTypeDemo()
      stdout <- Stdout()

      stdout.println("All service methods return HTTPResponse:")
      stdout.println("  status() -> HTTP status code")
      stdout.println("  content() -> response body")
      stdout.println("  contentType() -> MIME type")
      stdout.println("  cacheControl() -> caching rules")

Common mistakes

E50001 — The function getReturnInfo is not defined in this module. See ek9 -h E50001 for details.

Incorrect:

stdout.println(getReturnInfo())

Correct:

stdout.println("All service methods return HTTPResponse:")
Other ways to ask this
  • What is E07800 service missing return?
  • What return type do EK9 service methods require?
  • How do I construct an HTTPResponse in a service?

Coming from another language?

Java: Spring ResponseEntity<T> or JAX-RS Response. Python: Flask return (body, status_code). Go: w.WriteHeader(status); w.Write(body). Rust: HttpResponse::Ok().json(). EK9: HTTPResponse trait with status(), content(), contentType(), cacheControl(), contentLanguage().

Keywords: service, http, E07800, required, trait, content, return, HTTPResponse, function, status