Documentation
¶
Overview ¶
Package httpnode makes HTTP calls from a pipeline. It is named httpnode rather than http so that its own code can still refer to net/http.
A non-2xx status is data, not a failure: whether a 404 is a problem is the workflow's decision, so it arrives as Response.Status on a successful edge. A node error means no response was obtained at all.
Index ¶
- Constants
- func AssertStatusDefinition() node.Definition
- func BodyDefinition() node.Definition
- func BuildDefinition() node.Definition
- func FromURLDefinition() node.Definition
- func HeaderDefinition() node.Definition
- func RequestDefinition() node.Definition
- func StatusDefinition() node.Definition
- func WithBodyDefinition() node.Definition
- func WithHeaderDefinition() node.Definition
Constants ¶
const ( FromURLName = "http.from_url" WithHeaderName = "http.with_header" WithBodyName = "http.with_body" )
The capabilities that build a request from upstream data rather than from a static with block.
const ( StatusName = "http.status" HeaderName = "http.header" )
The capabilities that read one field of an HTTPResponse onto an edge.
const ( RequestName = "http.request" BodyName = "http.body" )
RequestName and BodyName are the capabilities a pipeline references with "uses:".
const AssertStatusName = "http.assert_status"
AssertStatusName is the capability a pipeline references with "uses: http.assert_status".
const BuildName = "http.build"
BuildName is the capability that builds a Request from a with block.
Variables ¶
This section is empty.
Functions ¶
func AssertStatusDefinition ¶
func AssertStatusDefinition() node.Definition
AssertStatusDefinition registers http.assert_status: *types.Response in, the same response out.
A non-2xx status is data, and http.request is right not to fail on one: only the workflow knows whether a 404 is a problem. This is how a workflow says that it is, without giving up that principle anywhere else. The step is opt-in, and a pipeline that wants to inspect a 404 simply does not add one.
The response passes through, so the steps that read it can depend on this one and will not run at all if the status is wrong.
The with block takes either an exact code or a range:
with: {equals: 200}
with: {min: 200, max: 299}
A range open at one end is allowed: min alone accepts anything at or above it, max alone anything at or below.
func BodyDefinition ¶
func BodyDefinition() node.Definition
BodyDefinition registers the http.body capability: *types.Response in, *types.Bytes out.
It is a one-line extractor and exists because the engine performs no implicit conversion between types. A pipeline that feeds an HTTP response into json.decode, which takes Bytes, must say so with a step, so the graph describes the whole computation rather than hiding part of it in the engine.
The body is shared, not copied: the Bytes it produces points at the same backing array as the response, which is safe because values are immutable.
func BuildDefinition ¶
func BuildDefinition() node.Definition
BuildDefinition registers the http.build capability: a source producing the *types.Request its with block declares.
It exists because the engine performs no implicit conversion. http.request consumes a Request, so a pipeline that calls a fixed URL says so in two steps: one that describes the call, one that makes it. A request built by a future node and a configured one then reach http.request the same way.
The URL is validated here, at compile time, so a typo fails p6e check rather than a production run.
func FromURLDefinition ¶
func FromURLDefinition() node.Definition
FromURLDefinition registers http.from_url: *types.Text in, *types.Request out.
http.build fixes its URL in a with block, which is right when the URL is known while writing the pipeline and wrong the moment it comes from data. A request whose URL is computed starts here instead, and http.with_header and http.with_body add to it.
The trade this makes is explicit and worth stating: http.build validates its URL at compile time, and a URL arriving on an edge cannot be validated until it arrives. Static type checking is unaffected; what is given up is static value checking of the URL, and only for the steps that opt into a computed one. The check still happens, as an invalid_input failure at the step that produced the bad URL rather than somewhere downstream.
func HeaderDefinition ¶
func HeaderDefinition() node.Definition
HeaderDefinition registers http.header: *types.Response in, *types.Text out.
The header named in the with block is read case insensitively. A header sent more than once yields its first value; a pipeline needing all of them wants a different node rather than a surprising one.
A missing header is an error unless the with block declares a default. There is no optional Text, so producing "" for an absent header would be indistinguishable from a header that is genuinely empty, and that value would then flow silently into a URL or a request body. Declaring the default makes the intent explicit and keeps the absent case visible:
with: {name: Retry-After, default: "0"}
The error is permanent: the same response will not grow the header on a retry.
func RequestDefinition ¶
func RequestDefinition() node.Definition
RequestDefinition registers the http.request capability: *types.Request in, *types.Response out.
A request with no method is sent as GET. Configuration is decoded and validated here, at compile time, and the client is built here too: it is shared by every execution of the step, which is what makes connection reuse possible.
func StatusDefinition ¶
func StatusDefinition() node.Definition
StatusDefinition registers http.status: *types.Response in, *types.Int out.
A non-2xx status is data, not a failure, and this is what makes that claim usable: without it the status never reaches an edge and no workflow can act on it. Whether a 404 is a problem stays the workflow's decision.
It takes no configuration. A with block is rejected rather than ignored.
func WithBodyDefinition ¶
func WithBodyDefinition() node.Definition
WithBodyDefinition registers http.with_body: (*types.Request, *types.Bytes) in, *types.Request out.
It takes no configuration. A with block is rejected rather than ignored.
The body is not wrapped, encoded, or given a content type: pairing it with http.with_header is how a pipeline says what the bytes are. Like http.with_header this produces a new request, and it shares the original's headers rather than copying them, which is safe because nothing mutates them.
func WithHeaderDefinition ¶
func WithHeaderDefinition() node.Definition
WithHeaderDefinition registers http.with_header: (*types.Request, *types.Text) in, *types.Request out.
The header name is configuration because it is known while writing the pipeline; the value is an input because it is not. An existing header of the same name is replaced.
It produces a new request rather than modifying the one it received. Values on edges are immutable, and this node has two reasons to respect that: the request it consumes may fan out to a sibling step, and a retried attempt receives the same input as the first.
Header names are canonicalised, so a pipeline that sets "content-type" over a request carrying "Content-Type" replaces it rather than producing both.
Types ¶
This section is empty.