How do CRUD operators map to URIs with path parameters?

← Web Services · Ref: Q660

EK9 maps service operators to HTTP verbs with semantic meaning. Each operator has a natural CRUD mapping.

OPERATOR MAPPING

  operator += :/           POST (create resource)
  operator -= :/{id}       DELETE (remove resource)
  operator :~: :/{id}      PATCH (partial update)
  operator :^: :/{id}      PUT (full replacement)

PATH PARAMETERS IN OPERATORS

Operators can include path parameters:

  operator -= :/{resourceId}
    -> resourceId as String
    <- response as HTTPResponse: ...

CONTENT BINDING IN OPERATORS

POST and PUT operators accept request body:

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

SEMANTIC ALIGNMENT

The operator meanings align with HTTP:

  += adds to collection -> POST creates
  -= removes from collection -> DELETE removes
  :~: merges partially -> PATCH updates fields
  :^: replaces entirely -> PUT replaces

See Q200 for CRUD overview. See Q657 for URI mapping. See Q658 for path parameters.

Example

defines module qa.webdeep.crudoperators

  defines service

    <?-
      Full CRUD service using operator-to-verb mapping.
      Each operator handles a different HTTP method.
    -?>
    Products :/products open

      // GET /products — list
      listProducts() :/
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `["widget", "gadget"]`
          override status() as pure
            <- rtn as Integer: 200
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "max-age=30"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

      // POST /products — create
      operator += :/
        -> productJson as String :=: CONTENT
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"created": 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 ?

      // DELETE /products/{productId} — remove
      operator -= :/{productId}
        -> productId as String
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: ""
          override status() as pure
            <- rtn as Integer: 204
          override contentType() as pure
            <- rtn as String: "text/plain"
          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

    CrudOperatorDemo()
      stdout <- Stdout()

      stdout.println("CRUD operators in service:")
      stdout.println("  += maps to POST /products")
      stdout.println("  -= maps to DELETE /products/{id}")

Common mistakes

E50001 — The function getCrudInfo is not defined in this module. See ek9 -h E50001 for details.

Incorrect:

stdout.println(getCrudInfo())

Correct:

stdout.println("CRUD operators in service:")

E50001 — The function getPostInfo is not defined in this module. See ek9 -h E50001 for details.

Incorrect:

stdout.println(getPostInfo())

Correct:

stdout.println("  += maps to POST /products")
Other ways to ask this
  • How do I use += for POST and -= for DELETE in services?
  • What is the operator to HTTP verb mapping in EK9?
  • How do service operators handle path parameters?

Coming from another language?

Java: Spring @PostMapping, @DeleteMapping, @PatchMapping, @PutMapping. Python: Flask methods=['POST']. Go: manual method switch. Rust: actix .post()/.delete(). EK9: operators += (POST), -= (DELETE), :~: (PATCH), :^: (PUT) with URI paths.

Keywords: operator, PUT, PATCH, E07860, dict, service, CRUD, http, mapping, DELETE, POST