How do I bind path parameters and request body in EK9 services?

← Web Services · Ref: Q202

EK9 services bind path parameters and request content automatically using URI templates and binding keywords.

PATH PARAMETERS (IMPLICIT)

Path segments in braces bind to parameters by name:

  byId() as GET for :/{id}
    -> id as String

The {id} in the path automatically binds to the id parameter.

EXPLICIT PATH BINDING

Use :=: PATH for explicit binding to a named path segment:

  -> itemId as String :=: PATH "item-id"

Binds parameter 'itemId' to the path segment named 'item-id'.

CONTENT BINDING

Access the request body with :=: CONTENT:

  -> content as String :=: CONTENT

The entire request body is bound to the parameter.

REQUEST BINDING

Access the full request object with :=: REQUEST:

  -> request as HTTPRequest :=: REQUEST

Provides access to all request information.

See Q199 for REST GET endpoints. See Q200 for CRUD operators. See Q112 for full service example.

Example

defines module qa.web.parameters

  defines service

    Products :/products open

      // Path parameter implicit binding
      byId() as GET for :/{id}
        -> id as String
        <- response as HTTPResponse?

        itemId <- String(id)
        response: (itemId) with trait HTTPResponse
          override content()
            <- rtn as String: `{"id": "${itemId}"}`
          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 ?

      // Content binding for POST body
      operator += :/
        -> content as String :=: CONTENT
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"received": true}`
          override status() as pure
            <- rtn as Integer: 201
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "no-store"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

  defines application

    ProductApp
      register Products()

  defines program

    ParameterBindingDemo()
      stdout <- Stdout()

      stdout.println("Path parameter binding:")
      stdout.println("  -> id as String (implicit from {id})")
      stdout.println("Content binding:")
      stdout.println("  -> content as String :=: CONTENT")
      stdout.println("Request binding:")
      stdout.println("  -> request as HTTPRequest :=: REQUEST")

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("Path parameter binding:")

Correct:

stdout.println("Path parameter binding:")
Other ways to ask this
  • How does automatic parameter binding work in EK9 services?
  • How do I access the request body in EK9?
  • How does parameter binding work in EK9 services?

Coming from another language?

Java: JAX-RS @PathParam("id"), @RequestBody. Python: Flask route('<id>') and request.json. Rust: axum Path(id) and Json(body) extractors. Go: mux.Vars(r)["id"] and io.ReadAll(r.Body). Kotlin: Ktor call.parameters["id"] and call.receive(). EK9: {id} in path auto-binds, :=: CONTENT for body, :=: REQUEST for full request.

Keywords: body, uri, service, http, content, rest, request, extract, path, parameter, bind