rest

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: AGPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package rest integrates an external HTTP-REST API as a service-task connector: a BPMN REST connector task calls a model-authored endpoint through the job path (ADR-0036/0067), mirroring how the dmn package delegates a decision to temis (ADR-0014). The integration inherits the job protocol's durability and non-blocking properties (ADR-0007):

  • A connector task creates a job carrying the reserved compiler.RestJobType. The processor never performs the outbound call itself, so it stays allocation-free (invariant I1) and free of any HTTP dependency.
  • The in-process Handler — a job worker — pulls those jobs, calls the REST API off the processor goroutine and after fsync (invariant I2, never inside applyToState / I4), writes the JSON response into the task's result variable, and completes the job, which drives the token onward.

Unlike the clio connector (ADR-0036), a REST task authors its full URL, method, headers, and query parameters in the model; credentials are never authored there — authentication (basic/bearer/apiKey) names a server-side secret the worker resolves at runtime (ADR-0041/0067), so a token never appears in a BPMN file.

Delivery is at-least-once (a crash between "the API accepted the call" and "job completed" replays the request); every request carries the job key as an Idempotency-Key header so a well-behaved API de-duplicates a replayed non-idempotent request rather than performing it twice.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Handler

func Handler(store state.Reader, lookup ProcessLookup, client Client, secret SecretResolver, tokens TokenProvider) job.OutputHandler

Handler builds a job handler that performs an HTTP-REST connector task. Register it with a job.Runner under the reserved compiler.RestJobTypeIndex via HandleWithOutput; the runner then pulls activatable REST jobs, and for each the handler resolves the connector task's method/url/headers/query/result-variable from the compiled process and calls the API through client — evaluating any FEEL url/header/query values over the variables the task sees, up its scope chain (the fx toggle, ADR-0067/0068), and sending as the JSON request body, for methods that carry one, what the task's input mappings map — or, with none, every variable it sees (ADR-0174) — keyed by the job key so an at-least-once retry de-duplicates. Authentication (basic/bearer/apiKey) is resolved through secret, which turns the model's secret *reference* into the credential at call time (ADR-0041); the token never lives in the model. When the task names a result variable, the JSON response is returned as that variable to be written back into the instance on completion. Returning an error fails the job (retry, then an incident, ADR-0061); the runner completes it only on success.

func NewTokenProvider added in v0.3.0

func NewTokenProvider() *tokenProvider

NewTokenProvider builds a token provider bounded by the shared connector call budget (nettimeout.HTTPClient), like the REST client itself.

Types

type Client

type Client interface {
	Do(ctx context.Context, r Request) (Response, error)
}

Client calls a REST API. It is an interface so the worker is testable without a live server.

type HTTPClient

type HTTPClient struct {
	// contains filtered or unexported fields
}

HTTPClient calls a real REST API over HTTP. It sends Request.Body as a JSON body (when present) to Request.URL with an Idempotency-Key header, and decodes a JSON response body. A non-2xx status is returned as an error so the job stays pending and is retried (at-least-once).

func NewHTTPClient

func NewHTTPClient() *HTTPClient

NewHTTPClient builds a REST HTTP client bounded by the shared connector call budget (nettimeout.Default). The worker runs on the run-loop goroutine, so an unbounded call would let a hung host stall the whole engine; see the nettimeout package doc. A per-connector configurable timeout is a follow-up (ADR-0067).

func (*HTTPClient) Do

func (c *HTTPClient) Do(ctx context.Context, r Request) (Response, error)

type Job added in v0.3.0

type Job struct {
	Method  string            `json:"method"`
	URL     string            `json:"url"`
	Headers map[string]string `json:"headers,omitempty"`
	Query   map[string]string `json:"query,omitempty"`
	Body    map[string]any    `json:"body,omitempty"`
	// Auth is the authored auth configuration, encoded as it sits in the compiled
	// process. It names a secret; it never carries one (see [compiler.RestAuth]).
	Auth string `json:"auth,omitempty"`
	// IdempotencyKey is the job key, so a call retried after a lease elapsed is
	// recognizable to the far end as the same one.
	IdempotencyKey string `json:"idempotencyKey,omitempty"`
	// Result names the process variable the response is written to; empty means the
	// model discards it.
	Result string `json:"resultVariable,omitempty"`
}

Job is a REST task with everything model-authored already evaluated. It is what travels with a leased job, and it has nowhere to put a secret.

func Resolve added in v0.3.0

func Resolve(store state.Reader, cp *compiler.CompiledProcess, detail *compiler.ConnectorTaskDetail, ei *model.ElementInstanceValue, elementInstanceKey, jobKey uint64) (Job, error)

Resolve turns a compiled REST task into a Job. Engine work by necessity: FEEL is compiled at deploy (ADR-0008/0015) and the scope lives in the store.

Auth is deliberately left unapplied. Applying it here would mean resolving the secret here, and then the credential would be in the job — which is the one thing the split exists to prevent.

type OAuthConfig added in v0.3.0

type OAuthConfig struct {
	TokenURL     string
	ClientID     string
	ClientSecret string
	Scope        string
}

OAuthConfig identifies one OAuth2 client-credentials token request (ADR-0152). TokenURL is the token endpoint; ClientID/ClientSecret authenticate the client; Scope is the optional space-delimited scope list. ClientSecret is the resolved value (from a secret reference, ADR-0041), never a reference here.

type ProcessLookup

type ProcessLookup func(defKey uint64) *compiler.CompiledProcess

ProcessLookup resolves a process-definition key to its compiled process. The worker uses it to find the method, URL, and result variable a REST job belongs to, so one handler serves every deployed process.

type Request

type Request struct {
	Method         string
	URL            string
	Headers        map[string]string
	Query          map[string]string
	Body           map[string]any
	IdempotencyKey string
}

Request is one HTTP call a REST connector task makes. URL is the full, model-authored endpoint (ADR-0067). Headers are set on the request (including any Authorization/api-key header the worker resolved from a secret); Query is appended to the URL. Body, when non-nil, is sent as a JSON request body (the worker attaches it only for methods that carry one). IdempotencyKey is deterministic (the job key), so an at-least-once retry can be de-duplicated by the target API.

type Response

type Response struct {
	Status int
	Body   any
}

Response is a REST call's outcome. Status is the HTTP status code; Body is the decoded JSON response (an object, array, number, string, bool or nil), or the raw response text when it is not valid JSON.

type Result added in v0.3.0

type Result struct {
	ResultVariable string
	Body           any
}

Result is what calling a Job produces.

func Run added in v0.3.0

func Run(ctx context.Context, j Job, client Client, secret SecretResolver, tokens TokenProvider) (Result, error)

Run applies the caller's own credential to a resolved job and makes the call. The in-process path calls it too, so there is one definition of what a resolved REST task means rather than two that drift — only whose secret store is in reach differs.

type SecretResolver

type SecretResolver func(ref string) string

SecretResolver returns the secret value for a reference name, or "" if unknown. The worker uses it to turn a REST task's authentication secret *reference* into the actual credential at call time (ADR-0041), so a token never lives in the model or the compiled process — only its reference does.

type TokenProvider added in v0.3.0

type TokenProvider interface {
	Token(ctx context.Context, cfg OAuthConfig) (string, error)
}

TokenProvider fetches an OAuth2 access token for a client-credentials grant. It is an interface so the worker is testable without a live token endpoint.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL