Why does EK9 reject a qualifier name on a REQUEST or CONTENT service parameter?
← Web Services · Ref: Q1325
EK9 service parameters bind to one HTTP source via :=:. Only PATH, QUERY and HEADER bindings take an extra qualifier name (the URI segment, query key or header name) so the runtime knows which value to extract. REQUEST and CONTENT bind to the whole request object or the whole request body respectively, so there is nothing to name. Adding a quoted qualifier to REQUEST or CONTENT triggers E07720 (SERVICE_HTTP_PARAM_QUALIFIER_NOT_ALLOWED) at the EXPLICIT_TYPE_SYMBOL_DEFINITION phase.
CORRECT
-> request as HTTPRequest :=: REQUEST -> body as String :=: CONTENT
INCORRECT
-> request as HTTPRequest :=: REQUEST "x" // E07720 -> body as String :=: CONTENT "payload" // E07720
The fix is simply to delete the qualifier name. Contrast with E07710 (missing qualifier), which fires when PATH, QUERY or HEADER lacks the name they DO require.
See Q658 for path parameter binding. See Q868 for service parameter types.
Example
defines module qa.webdeep.service.param.qualifier defines constant JSON_RESPONSE <- "application/json" defines service <?- Service showing the bindings that do NOT take a qualifier name. REQUEST binds the whole request, CONTENT binds the whole body. -?> EchoService :/echo open // REQUEST binds the full HTTPRequest - no qualifier name allowed. describe() as GET for :/details -> request as HTTPRequest :=: REQUEST <- response as HTTPResponse: (incoming: request.content()) with trait HTTPResponse override content() <- rtn as String: `{"request": "${incoming}"}` override status() as pure <- rtn as Integer: 200 override contentType() as pure <- rtn as String: JSON_RESPONSE override cacheControl() as pure <- rtn as String: "no-cache" override contentLanguage() as pure <- rtn as String: "en" default operator ? // CONTENT binds the whole request body - no qualifier name allowed. operator += :/ -> body as String :=: CONTENT <- response as HTTPResponse: (received: body) with trait HTTPResponse override content() <- rtn as String: `{"received": "${received}"}` override status() as pure <- rtn as Integer: 201 override contentType() as pure <- rtn as String: JSON_RESPONSE override cacheControl() as pure <- rtn as String: "no-store" override contentLanguage() as pure <- rtn as String: "en" default operator ? defines application EchoApp register EchoService() defines program QualifierDemo() stdout <- Stdout() stdout.println("No qualifier name: :=: REQUEST and :=: CONTENT") stdout.println("Qualifier name required: :=: PATH, :=: QUERY, :=: HEADER")
Common mistakes
E07720 — REQUEST binds the whole HTTP request and CONTENT binds the whole request body, so neither accepts a qualifier name. The quoted qualifier (only valid for PATH, QUERY and HEADER, which need to name the segment/key/header) is rejected as E07720. Remove the qualifier so the binding reads ':=: REQUEST'. See ek9 -h E07720 for details.
Incorrect:
-> request as HTTPRequest :=: REQUEST "not-required"
Correct:
-> request as HTTPRequest :=: REQUEST
Other ways to ask this
- What triggers E07720 SERVICE_HTTP_PARAM_QUALIFIER_NOT_ALLOWED?
- Why can't I add a name after :=: REQUEST or :=: CONTENT?
- Which HTTP service bindings take a qualifier name and which do not?
Coming from another language?
Java Spring: @RequestBody and the HttpServletRequest argument take no name, while @RequestParam/@PathVariable/@RequestHeader take a key string; mixing them up is silently accepted or fails at runtime. ASP.NET / Flask / Go behave similarly with no compile-time guard. EK9 enforces the distinction at compile time: REQUEST and CONTENT must have no qualifier, PATH/QUERY/HEADER must have one.
Keywords: service, http, binding, parameter, E07720, qualifier, QUERY, CONTENT, REQUEST, HEADER