Skip to content

Webservice Response

Builds the HTTP response that a webservice rule sends back to its caller. You write one YAML map, and each key in it either contributes to the response payload or sets one part of the HTTP envelope: the status, the headers, the cookies, the redirect target.

Without this op a webservice rule still answers, but with whatever the rule happened to return and a __msg entry in the payload saying no webservice response was set on the rule. Reach for this op as soon as the caller cares about the shape of the answer.

The op has no effect in any other rule type. It writes its values away and nothing reads them back, with no warning in the designer and no error at run time.

Response YAML data: or body: status: headers: cookies: location: payload, merged envelope, one per key HTTP response, format from the URL both data: and body: in the same request stops the rule and returns a fault

Fields

Response

The only control on the form. A YAML editor holding one map, where every top-level key is one of the names in the table below. An unknown key is accepted and then ignored when the response is built, so a typo such as statsu: 404 costs you the status and says nothing about it.

${var} placeholders expand against the stash in values, at any nesting depth, inside nested maps and lists alike. Keys are left untouched, so ${foo}: 1 reaches the caller with the literal text as the key name. ${ws_params.foo} reads a query parameter and ${ws_headers.host} reads a request header.

The editor parses the YAML when you save the op, not when the rule runs. That has two consequences. Invalid YAML raises a dialog and blocks the save, so a broken response never reaches a running rule. And comments are dropped, key order is not kept, and the map comes back sorted alphabetically the next time you open the form. Put any explanation you need in the op's Note tab instead.

Leave the field empty and the op does nothing at all. The same happens when the top level is a list rather than a map. Neither case logs anything, and the caller gets the default no-response payload.

Response keys

Key Effect
data: contributes to a structured payload, serialised according to the calling URL
body: sends a string back verbatim, for text or file contents
status: sets the HTTP status code
headers: a map of header names to values
header: accepted, applied, and changes nothing
content_type: shorthand for the Content-Type header
cookies: a map of cookie names to cookie settings
location: sets the Location header and leaves the status alone
redirect: sets Location and forces the status to 302
write: pushes a chunk straight to the client

data: and body:

The two are mutually exclusive, and the check spans the whole request rather than a single op. If one op sets body: and a second op anywhere later in the rule sets data:, the request fails with a message quoting the first 20 characters of each side. Decide which of the two the rule uses and stay with it on every branch.

data: accepts a map or a list. A map merges key by key into whatever earlier ops contributed, so you can build a payload in pieces. A list replaces the payload outright, which is what you want for an array response and a trap when you meant to add to a map: once a list is in place, a later map data: fails with the same body-and-data message, naming your list as the body. Anything else, a bare string or a number, fails with an invalid value message.

body: is a plain string. It is the right choice for CSV, HTML or file contents. On a /json/ URL it is not used at all and the caller receives {}, because the JSON serialiser only knows how to render a structure. Two ops both setting body: do not fail, unlike every other key here. The later one silently replaces the earlier one.

Everything else

Each of the remaining keys may be set once per request. Setting the same one twice fails with a duplicate method message, unless both values are maps, in which case they merge. headers: and cookies: therefore split across several ops, while status: and content_type: do not.

The envelope keys are applied once the rule has finished, in a fixed order that ignores the order you wrote them in: cookies, status, redirect, location, write, content_type, headers, header. Two consequences follow. redirect: is applied after status: and always sets 302, so combining the two loses the code you asked for. And headers: is applied after content_type:, so a Content-Type inside the map wins.

Header names are rewritten to HTTP form on the way out. Every _ becomes a - and each word is capitalised, so my_header reaches the caller as My-Header.

A value the response refuses, a map where a string was expected for instance, fails the request with an error naming the key.

header: is a dead end. The single value it carries is read as the name of a header to look up rather than a header to set, so the entry changes nothing, and neither the designer nor the log says so. Use headers: with a map.

write: pushes a chunk straight to the client and commits the response headers at the moment it runs. It runs ahead of content_type:, headers: and header:, so anything those set afterwards never reaches the caller.

A request that reaches the rule answers 200 whether the rule finished or blew up. status: and redirect: are the only keys that change that, so an API contract that wants 4xx on an error branch needs you to set the code by hand on that branch.

Cookie entries take the shape below. expires and max-age both accept an absolute date or a relative offset such as +3M or +2D.

cookies:
   my-cookie:
      value: a cookie value
      expires: +3M
      path: /
      domain: mydomain
      secure: 1
      httponly: 1

What the caller gets when the rule fails

A failure here, or in any other op of the rule, is not turned into an HTTP error. The status stays at whatever the envelope keys set, 200 by default, and the caller receives a single ws_response entry holding a Fault map with the error text, alongside _RETURN_CODE and _RETURN_TEXT values that sit inside that payload and never reach the HTTP status line. Anything data: had collected up to that point is discarded. The error is also written to the server log.

Clients that only check the HTTP status will read a failed request as a success. Have the caller look for Fault in the payload, or set status: yourself on the branches that can fail.

The calling URL decides the format

The response format comes from the URL the caller used, not from this op: http(s)://clariveserver/rule/[json|yaml|xml|raw]/[rule-id]. An unrecognised format behaves like raw. A data: payload is serialised to JSON, YAML or XML accordingly, and under raw a map comes back as YAML text. ${ws_format} in the stash tells the rule which one was asked for, so one rule can answer differently per format.

content_type: and headers: are applied after the serialiser has set its own content type, so they override it when you need them to.

Combining with other ops

Guard the response so each branch answers once. IF var condition THEN picks between a success and an error response, and ELSE carries the other half. Two of these ops firing on the same request is the most common source of the duplicate-key failure.

Gather the values first. SET VAR and EVAL JavaScript build the structures that data: then references through ${var}.

Web Request is the other side of the same coin: it calls a webservice, this op answers one.

Examples

A plain acknowledgement.

Response:
  status: 200
  data:
    status: OK

An error response driven by a stash variable, sent from inside a conditional branch.

Response:
  status: 404
  data:
    errors: ${foo_errors}

A CSV download. body: carries the text and the two envelope keys make the browser save it.

Response:
  content_type: text/csv
  headers:
    Content-Disposition: attachment;filename=example.csv
  body: |
    name,count
    bar,12
    baz,7