Skip to content

Commit

Permalink
handler update
Browse files Browse the repository at this point in the history
  • Loading branch information
kraftp committed Oct 9, 2023
1 parent 7105201 commit b5e718a
Showing 1 changed file with 57 additions and 14 deletions.
71 changes: 57 additions & 14 deletions docs/tutorials/handlers-tutorial.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,71 @@
---
sidebar_position: 2
title: HTTP handlers
description: Learn how to register Operon HTTP handlers
title: HTTP Serving
description: Learn how to serve HTTP requests
---

Operon lets you declare HTTP handlers to make your workflows available through HTTP.
Under the hood, `npx operon start` runs a [Koa](https://koajs.com/) server exposing your handlers.
In this guide, you'll learn how to serve HTTP requests with Operon.
Any Operon function can be made into an HTTP endpoint by annotating it with an _endpoint decorator_.
For example:

```tsx
importHandlerContext, GetApi } from '@dbos-inc/operon'

export class Hello {
```javascript
@GetApi('/greeting/:name')
static async greetingEndpoint(ctx: HandlerContext, name: string) {
return `Greeting, ${name}`;
return `Greeting, ${name}`;
}
```

We currently support two endpoint decorators, [`GetApi`](../api-reference/decorators#getapi) (HTTP `GET`) and [`PostApi`](../api-reference/decorators#postapi) (HTTP `POST`).
Each associates a function with an HTTP URL.

### Handlers

A function annotated with an endpoint decorator but no other decorators like is called a _handler_ and must take a [`HandlerContext`](..) as its first argument, like in the example above.
Handlers can invoke other functions and directly access HTTP requests and responses.
However, Operon makes no guarantees about handler execution: if a handler fails, it is not automatically retried.
You should use handlers when you need to access HTTP responses directly or when you're doing a lightweight task that doesn't need the strong guarantees of transactions and workflows.

You don't need a handler to serve a transaction, workflow, or communicator from an HTTP URL.
You can also annotate your function with an endpoint decorator in addition to its [`@OperonTransaction`](../api-reference/decorators#operontransaction), [`@OperonWorkflow`](../api-reference/decorators#operonworkflow), or [`@OperonCommunicator`](../api-reference/decorators#operoncommunicator) decorator.
For example (from our [quickstart](..)):

```javascript
@PostApi('/clear/:name')
@OperonTransaction()
static async clearTransaction(txnCtxt: KnexTransactionContext, name: string) {
// Delete greet_count for a user.
await txnCtxt.client<operon_hello>("operon_hello")
.where({ name: name })
.delete()
return `Cleared greet_count for ${name}!\n`
}
}
```

Operon operations must be declared as static methods of a class -- here, `Hello`. To register a `GET` HTTP handler, use the `@GetApi` decorator with your handler path.
### Inputs and HTTP Requests

Any Operon method invoked via HTTP request can access the raw request from its `context.request` field.

If a function has arguments other than its context, Operon attempts to automatically parse them from the HTTP request.
Arguments can be parsed from three places:

1. From a URL query string parameter with the same name.
2. From an HTTP body field with the same name.
3. From an HTTP path parameter, if one is specified in the decorated URL.

Input parsing can be configured using the [`@ArgSource`](../api-reference/decorators#argsource) parameter decorator.

By default, Operon automatically validates parsed inputs, returning an error if a function is missing required inputs or if the input received is of a different type than specified in the method signature.
Validation can be turned off at the class level using [`@DefaultArgOptional`](..) or controlled at the parameter level using [`@ArgRequired`](..) and [`@ArgOptional`](..).

### Outputs and HTTP Responses

By default, if an Operon function invoked via HTTP request returns successfuly, its return value is sent in the body of the HTTP response with status code `200`.
If the function throws an exception, the error message is sent in the response body with a `400` or `500` status code.

## `GetApi(url: string)`
If you need custom HTTP response behavior, you can use a handler to access the HTTP response directly.
Operon uses [Koa](https://koajs.com/) for HTTP serving internally, so the raw response can be accessed via the `.koaContext.response` field of [`HandlerContext`](..), which returns a [Koa response](https://koajs.com/#response).

`url` is the endpoint you wish to register your handler under. Under the hood, Operon uses [koa-router](https://github.com/ZijianHe/koa-router), which uses [path_to_regex](https://github.com/pillarjs/path-to-regexp) to translate this `url` to a regular expression for the router to match incoming requests.
### Middleware

## `ctx: HandlerContext`
Operon supports running custom [Koa](https://koajs.com/) middleware for serving HTTP requests.
Middleware is configured at the class level through the [`@KoaMiddleware`](../api-reference/decorators@koamiddleware) decorator.

0 comments on commit b5e718a

Please sign in to comment.