---
id: web--rest-api-listener
title: "Rest handler"
summary: "Handles one REST operation (method + route) behind an **Http listener**: it accepts only matching requests, extracts route, query and body parameters into a typed record and emits it. Connect several Rest handlers to the same listener `Output` pin, one per operation; each request goes to the handler(s) whose route matches. It also serves an OpenAPI (`swagger.json`) document for all Rest handlers of the flow."
audience: user
keywords: "input, output, validate, route, typename, routespecification"
---
# Rest handler

Handles one REST operation (method + route) behind an **Http listener**: it accepts only matching requests, extracts route, query and body parameters into a typed record and emits it. Connect several Rest handlers to the same listener `Output` pin, one per operation; each request goes to the handler(s) whose route matches. It also serves an OpenAPI (`swagger.json`) document for all Rest handlers of the flow.

## Pins

| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | `Viaducta.Plugins.Http.Types.WebHttpRequest` | Request from the Http listener `Output` pin. |
| Output | output | generated (see Behaviour) | Parameters of the call as a typed record. |
| Validate | validate | `Viaducta.Plugins.RestApiListener.RestRequest` | Called before the output with the parsed route (`HttpRequest`, `HostName`, `Port`, `BaseUrl`, `BaseUrlParts`, `HttpMethod`, `MethodName`, `QueryString`, `RouteParameterValues`). An error rejects the request. |

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `Route` | route builder | | Required. Display form of the route, e.g. `/api/GetOrder/{id}`. Regenerated from `RouteSpecification` (reconfigures the component). |
| `TypeName` | string | | Name of the generated output type. Empty: `<name>Request`. Changing it reconfigures the component. |
| `RouteSpecification` | hidden string (JSON) | | The actual definition, written by the route builder dialog. |

### RouteSpecification format

```json
{
  "service": "Orders",
  "baseUrl": "/api",
  "name": "GetOrder",
  "httpMethod": "GET",
  "parameters": [
    { "name": "id", "position": 2, "type": "System.Int32" },
    { "name": "details", "position": 3, "type": "System.Boolean", "defaultValue": "false" }
  ],
  "returnTypeContainer": "Instance",
  "returnType": ""
}
```

- `httpMethod`: upper case `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`.
- `position`: `1` FromBody, `2` FromRoute, `3` FromQuery. `type`: .NET full type name (`System.String`, `System.Int32`, ...) or the full name of a flow type.
- `service` (OpenAPI tag), `returnTypeContainer` (`Instance`, `List`, `Dictionary`) and `returnType` are only used for the OpenAPI document.
- After editing the JSON by hand, the `Route` field must be reconfigured to regenerate the output type.

## Behaviour

- Route template: `<baseUrl>/<name>/{routeParam1}/{routeParam2}...`. A request matches when the method is equal (ignoring case) and its **full path** has the same number of segments (empty segments are skipped), fixed segments equal (case-insensitive) and route parameter segments filled. So `baseUrl` must contain the listener path: listener `http://0.0.0.0:9000/api` + `baseUrl` `/api` + `name` `GetOrder` → `GET /api/GetOrder/42`. Query parameters don't take part in matching. The route is compiled once when the flow starts.
- Output type: no parameters → `Viaducta.TypeSystem.Metadata.NoInputData`; a single FromBody parameter whose type is a flow type → that type; otherwise a generated class (`TypeName`) in the flow namespace with one property per parameter. Saving the route or changing `TypeName` rebuilds it and removes the type generated before.
- Values: the body JSON (`Body`, or `ByteBody` as UTF-8 when the listener keeps the raw body) is read as the output type; an empty body leaves the defaults. Then route and query values are written over it, so a route or query value always wins over the same property in the body. FromRoute - the segment, unescaped on its own (`%2F` stays inside the value, `+` stays `+`), converted to the property type. FromQuery - the first value (name exact, else ignoring case) converted; missing (or empty for non-text types) → the parameter's `defaultValue`, else `null` for nullable types, else 400.
- Validate pin: gets the `RestRequest` after the route matched, so `RouteParameterValues` holds the route values; an error there stops the request.
- A request that can't be read - body that is not JSON of the output type, a route or query value of the wrong type, a missing required query parameter - is answered `400` with the listener's JSON error (`code` 400) and nothing is emitted.
- A `GET` whose last path segment is `swagger.json` is answered with an OpenAPI 3.1 document (JSON) of all Rest handlers in the flow; only one Rest handler per request answers it (the first one the listener asks). Paths carry the route placeholders (`/api/GetOrder/{id}`); route parameters are required, query parameters are optional when they have a `defaultValue` or a nullable type; the body is the parameter's flow type when it is the only parameter, else an object `<Name>Body` with one property per body parameter; the answer is `returnType` (`List` = array, `Dictionary` = object); `400` and `500` carry the listener's JSON error (`ViaductaError`). The server is the request's scheme and host, or `X-Forwarded-Proto` / `X-Forwarded-Host` / `X-Forwarded-Prefix` when a proxy sends them. The document is written by Viaducta.CodeGen (`OpenApiWriter.ForRestApi`) and cached per server.
- No `Output` connection: nothing is emitted and the listener returns `500` (no response sent).

## Notes

- With the generated class, the FromBody JSON must contain the properties of that class (one property per parameter), not the bare body object.
- Errors in the flow after the Rest handler are returned by the listener as `500` JSON errors.
- When no Rest handler matches, nothing handles the request and the listener answers `500` "The response ... was never sent".
- Two Rest handlers with the same method and route shape are both called; the OpenAPI document lists the first one and names the other in `x-viaducta-contract.warnings`.

## Example

Http listener (`http://0.0.0.0:9000/api`) → **Rest handler** (`GET /api/GetOrder/{id}`) → Database reader → Json serializer → Http response
