Why can't I mix HTTPRequest with other parameters in an EK9 service operation?
← Web Services · Ref: Q1328
When a service operation takes the full request via :=: REQUEST (an HTTPRequest), that parameter must be the ONLY parameter on the operation. Adding any second parameter — a CONTENT binding, a PATH segment, anything — triggers E07780 (SERVICE_REQUEST_BY_ITSELF).
The rule exists because HTTPRequest already gives you the entire request — path segments, query string, headers and body. Mixing it with individually-bound parameters duplicates the binding and creates two sources of truth for the same data.
CORRECT PATTERN
process() as POST for :/process -> request as HTTPRequest :=: REQUEST
Read the body, headers and query values from the request inside the method body via request.content() and friends.
INCORRECT PATTERN
process() as POST for :/process -> request as HTTPRequest :=: REQUEST body as String :=: CONTENT
The extra body parameter alongside the full request raises E07780.
See Q202 for parameter binding. See Q868 for valid path-parameter types.
Example
defines module qa.webdeep.service.request.only defines constant JSON_RESPONSE <- "application/json" defines service <?- Operation that binds the FULL request via :=: REQUEST. HTTPRequest is the only parameter, so E07780 is not raised. Any path/query/body value is read from the request inside the body. -?> ItemService :/items open process() as POST for :/process -> request as HTTPRequest :=: REQUEST <- response as HTTPResponse: (request: request) with trait HTTPResponse override content() <- rtn as String: `{"received": "${request.content()}"}` 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 ItemApp register ItemService() defines program HttpRequestOnlyDemo() stdout <- Stdout() stdout.println("HTTPRequest must be the ONLY parameter on an operation.") stdout.println("Read path/query/body values from the request inside the body.")
Common mistakes
E07780 — An operation that binds the full request with :=: REQUEST must have HTTPRequest as its ONLY parameter. The extra CONTENT-bound body parameter makes the operation take more than one parameter, so E07780 fires. Drop the extra parameter and read the body from the request inside the method body via request.content(). See ek9 -h E07780 for details.
Incorrect:
process() as POST for :/process -> request as HTTPRequest :=: REQUEST body as String :=: CONTENT
Correct:
process() as POST for :/process -> request as HTTPRequest :=: REQUEST
Other ways to ask this
- What triggers E07780 SERVICE_REQUEST_BY_ITSELF?
- Why must HTTPRequest be the only parameter on a service operation?
- How do I get a path or query value when I also need the full HTTPRequest?
Coming from another language?
Java Spring: a handler may freely mix HttpServletRequest with @PathVariable/@RequestParam — nothing prevents the duplication. C# ASP.NET: HttpContext plus bound parameters coexist. Go net/http: you read *http.Request and also parse mux.Vars(r) together. EK9: the compiler forbids the mixture at compile time — if you take the full HTTPRequest you take only that and extract the rest from it.
Keywords: HTTPRequest, binding, service, rest, E07780, REQUEST, parameter, http