How do I extract path parameters in EK9 services?

← Web Services · Ref: Q658

EK9 services extract path parameters using :/{paramName} syntax. The path variable binds to a method parameter of the same name.

PATH PARAMETER

Declare a path variable in the URI:

  byId() as GET for :/{orderId}
    -> orderId as String
    <- response as HTTPResponse: ...

The server extracts orderId from the URL path.

CAPTURE PATTERN FOR DYNAMIC RESPONSE

Path parameters are NOT in scope inside the dynamic HTTPResponse class body. To use a path parameter in response content, capture it in the dynamic class expression:

  <- response as HTTPResponse: (capturedId: orderId) with trait HTTPResponse
    override content()
      <- rtn as Bytes: Bytes().withUtf8(`{"id": "${capturedId}"}`)

The captured variable is accessible within the dynamic class methods.

CONTENT BINDING

Use :=: CONTENT for request body:

  operator += for :/
    -> body as String :=: CONTENT

The request body is bound to the 'body' parameter.

HTTPRESPONSE RETURN

Every service method must return HTTPResponse:

  <- response as HTTPResponse: ...

See Q657 for URI mapping basics. See Q200 for CRUD operators. See Q201 for HTTP responses. See Q659 for HTTPResponse requirements. See Q660 for CRUD operators.

Example

#!ek9
defines module qa.webdeep.pathbinding

  defines service

    <?-
      Service demonstrating path parameter extraction
      and content body binding.
    -?>
    Orders for :/orders open

      // GET /orders/{orderId} — extract path param
      byId() as GET for :/{orderId}
        -> orderId as String
        <- response as HTTPResponse: (capturedId: orderId) with trait HTTPResponse
          override content()
            <- rtn as Bytes: Bytes().withUtf8(`{"orderId": "${capturedId}"}`)
          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 ?

      // POST /orders — content body binding
      operator += for :/
        -> orderJson as String :=: CONTENT
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as Bytes: Bytes().withUtf8(`{"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

    OrderApp
      register Orders()

  defines program

    PathParameterDemo()
      stdout <- Stdout()

      stdout.println("Path parameter binding:")
      stdout.println("  GET /orders/{orderId} -> byId(orderId)")
      stdout.println("  POST /orders with CONTENT -> operator +=")

Common mistakes

E07700 — Path parameters in the URI must have a matching method parameter with the same name. If the URI declares {orderId}, the method must have a parameter named orderId. See ek9 -h E07700 for details.

Incorrect:

-> orderNumber as String

Correct:

-> orderId as String
Other ways to ask this
  • How does PATH binding work in EK9 services?
  • How do I get URL path variables in service methods?
  • What is E07880 service parameter binding error?

Coming from another language?

Java: @PathVariable('orderId') String orderId. Python: Flask route('<orderId>'). Go: mux.Vars(r)['orderId']. Rust: web::Path<String>. EK9: ':/{orderId}' in URI, '-> orderId as String' in parameter list.

Keywords: E07880, REST, URL, binding, extract, http, parameter, path, service, variable