Why can't I mix HTTPContext with QUERY or PATH parameters in an EK9 service method?

← Web Services · Ref: Q1330

When an EK9 service method binds the full request via :=: CONTEXT, the HTTPContext parameter must be the ONLY parameter. Adding individual :=: QUERY or :=: PATH bindings alongside it raises E07792: a method has exactly one binding strategy.

HTTPContext carries security and connection metadata, not the request data: principal(), isAuthenticated(), isSecure(), remoteAddress(), requestId(), header(name), contentType(), cookie(name) and withPrincipal(identity). It has NO query, path or body accessors.

So choose by what the method needs:
1. Use HTTPContext ALONE when the method needs only that metadata (who is calling, request id, a header or cookie).
2. When the method needs query, path or body values, bind them as individual qualified parameters (:=: PATH, :=: QUERY, :=: HEADER, :=: CONTENT) and do NOT take an HTTPContext at all.

See Q202 for parameter binding and Q945 for parameter qualifiers.

Example

defines module qa.webdeep.service.httpcontext

  defines constant

    JSON_TYPE <- "application/json"

  defines service

    <?-
      Search service demonstrating the correct use of HTTPContext.
      The method binds the request context via :=: CONTEXT and uses ONLY
      that single parameter. HTTPContext carries metadata (principal,
      headers, cookies, request id), not query or path values. A method
      that needs those binds them with :=: QUERY/PATH instead and takes
      no HTTPContext - mixing the two raises E07792.
    -?>
    SearchService :/search open

      search() as GET for :/results
        -> ctx as HTTPContext :=: CONTEXT
        <- response as HTTPResponse: (reqId: ctx.requestId()) with trait HTTPResponse
          override content()
            <- rtn as Bytes: Bytes().withUtf8(`{"requestId": "${reqId}"}`)
          override status() as pure
            <- rtn as Integer: 200
          override contentType() as pure
            <- rtn as String: JSON_TYPE
          override cacheControl() as pure
            <- rtn as String: "no-cache"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

  defines application

    SearchApp
      register SearchService()

  defines program

    HttpContextDemo()
      stdout <- Stdout()
      stdout.println("HTTPContext must be the ONLY service-method parameter.")
      stdout.println("It carries metadata only: principal, headers, cookies, request id.")
      stdout.println("To read query or path values, bind them with :=: QUERY or :=: PATH")
      stdout.println("and do not take HTTPContext at all (mixing them is E07792).")

Common mistakes

E07792 — HTTPContext (:=: CONTEXT) must be the only parameter, so adding a :=: QUERY binding alongside it triggers E07792. HTTPContext has no query accessor; a method that needs the query value binds it with :=: QUERY and does not take HTTPContext. See ek9 -h E07792 for details.

Incorrect:

        ->
          ctx as HTTPContext :=: CONTEXT
          term as String :=: QUERY "q"

Correct:

        -> ctx as HTTPContext :=: CONTEXT
Other ways to ask this
  • What triggers E07792 HTTPContext mixed with other params?
  • Why must HTTPContext be the only parameter in a service method?
  • How do I access query and path values when using HTTPContext in EK9?

Coming from another language?

Java Spring: you may freely combine HttpServletRequest with @RequestParam/@PathVariable in the same handler - no compiler objection, JAX-RS allows @Context HttpServletRequest beside @QueryParam. EK9 instead makes the mix a compile-time error (E07792): HTTPContext and individual bindings are mutually exclusive, so a method has exactly one, unambiguous binding strategy.

Keywords: service, QUERY, PATH, CONTEXT, parameter, web, binding, HTTPContext, E07792