cloudevents

package
v0.0.0-...-20d7626 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2019 License: Apache-2.0 Imports: 16 Imported by: 0

README

Knative CloudEvents SDK

This library produces CloudEvents in version 0.1 compatible form. To learn more about CloudEvents, see the Specification.

There are two roles the SDK fulfills: the producer and the consumer. The producer creates a cloud event in either Binary or Structured request format. The producer assembles and sends the event through an HTTP endpoint. The consumer will inspect the incoming HTTP request and select the correct decode format.

This SDK should be wire-compatible with any other producer or consumer of the supported versions of CloudEvents.

Getting Started

CloudEvents acts as the envelope in which to send a custom object. Define a CloudEvent type for the events you will be producing.

Example CloudEvent Type: dev.knative.cloudevent.example

Select a source to identify the originator of this CloudEvent. It should be a valid URI which represents the subject which created the CloudEvent (cloud bucket, git repo, etc).

Example CloudEvent Source: https://github.com/knative/pkg#cloudevents-example

And finally, create a struct that will be the data inside the CloudEvent, example:


type Example struct {
    Sequence int    `json:"id"`
    Message  string `json:"message"`
}

Producer

The producer creates a new cloudevent.Client, and then sends 10 Example events to "http://localhost:8080".


package main

import (
    "knative.dev/pkg/cloudevents"
    "log"
)

type Example struct {
    Sequence int    `json:"id"`
    Message  string `json:"message"`
}

func main() {
    c := cloudevents.NewClient(
        "http://localhost:8080",
        cloudevents.Builder{
            Source:    "https://github.com/knative/pkg#cloudevents-example",
            EventType: "dev.knative.cloudevent.example",
        },
    )
    for i := 0; i < 10; i++ {
        data := Example{
            Message:  "hello, world!",
            Sequence: i,
        }
        if err := c.Send(data); err != nil {
            log.Printf("error sending: %v", err)
        }
    }
}

Consumer

The consumer will listen for a post and then inspect the headers to understand how to decode the request.


package main

import (
    "context"
    "log"
    "net/http"
    "time"

    "knative.dev/pkg/cloudevents"
)

type Example struct {
    Sequence int    `json:"id"`
    Message  string `json:"message"`
}

func handler(ctx context.Context, data *Example) {
    metadata := cloudevents.FromContext(ctx)
    log.Printf("[%s] %s %s: %d, %q", metadata.EventTime.Format(time.RFC3339), metadata.ContentType, metadata.Source, data.Sequence, data.Message)
}

func main() {
    log.Print("listening on port 8080")
    log.Fatal(http.ListenAndServe(":8080", cloudevents.Handler(handler)))
}

Request Formats

CloudEvents Version 0.1
Binary

This is default, but to leverage binary request format:


    c := cloudevents.NewClient(
        "http://localhost:8080",
        cloudevents.Builder{
            Source:    "https://github.com/knative/pkg#cloudevents-example",
            EventType: "dev.knative.cloudevent.example",
            Encoding: cloudevents.BinaryV01,
        },
    )

Structured

To leverage structured request format:


    c := cloudevents.NewClient(
        "http://localhost:8080",
        cloudevents.Builder{
            Source:    "https://github.com/knative/pkg#cloudevents-example",
            EventType: "dev.knative.cloudevent.example",
            Encoding: cloudevents.StructuredV01,
        },
    )

Documentation

Overview

Package cloudevents implements utilities for handling CloudEvents. For information on the spec, see https://github.com/cloudevents/spec/blob/v0.1/http-transport-binding.md and https://github.com/cloudevents/spec/blob/v0.1/spec.md

Index

Constants

View Source
const (
	// HeaderCloudEventsVersion is the header for the version of Cloud Events
	// used.
	HeaderCloudEventsVersion = "CE-CloudEventsVersion"

	// HeaderEventID is the header for the unique ID of this event.
	HeaderEventID = "CE-EventID"

	// HeaderEventTime is the OPTIONAL header for the time at which an event
	// occurred.
	HeaderEventTime = "CE-EventTime"

	// HeaderEventType is the header for type of event represented. Value SHOULD
	// be in reverse-dns form.
	HeaderEventType = "CE-EventType"

	// HeaderEventTypeVersion is the OPTIONAL header for the version of the
	// scheme for the event type.
	HeaderEventTypeVersion = "CE-EventTypeVersion"

	// HeaderSchemaURL is the OPTIONAL header for the schema of the event data.
	HeaderSchemaURL = "CE-SchemaURL"

	// HeaderSource is the header for the source which emitted this event.
	HeaderSource = "CE-Source"

	// HeaderExtensionsPrefix is the OPTIONAL header prefix for CloudEvents extensions
	HeaderExtensionsPrefix = "CE-X-"

	// Binary implements Binary encoding/decoding
	Binary binary = 0
)
View Source
const (
	// ContentTypeStructuredJSON is the content-type for "Structured" encoding
	// where an event envelope is written in JSON and the body is arbitrary
	// data which might be an alternate encoding.
	ContentTypeStructuredJSON = "application/cloudevents+json"

	// ContentTypeBinaryJSON is the content-type for "Binary" encoding where
	// the event context is in HTTP headers and the body is a JSON event data.
	ContentTypeBinaryJSON = "application/json"

	// HeaderContentType is the standard HTTP header "Content-Type"
	HeaderContentType = "Content-Type"

	// CloudEventsVersion is a legacy alias of V01CloudEventsVersion, for compatibility.
	CloudEventsVersion = V01CloudEventsVersion
)
View Source
const (
	// Structured implements the JSON structured encoding/decoding
	Structured structured = 0
)
View Source
const (
	// V01CloudEventsVersion is the version of the CloudEvents spec targeted
	// by this library.
	V01CloudEventsVersion = "0.1"
)
View Source
const (
	// V02CloudEventsVersion is the version of the CloudEvents spec targeted
	// by this library.
	V02CloudEventsVersion = "0.2"
)

Variables

This section is empty.

Functions

func Handler

func Handler(fn interface{}) http.Handler

Handler creates an EventHandler that implements http.Handler If the fn parameter is not a valid type, will produce an http.Handler that also conforms to error and will respond to all HTTP requests with that error. Valid types of fn are:

* func() * func() error * func() (anything, error) * func() (anything, EventContext, error) * func(context.Context) * func(context.Context) error * func(context.Context) (anything, error) * func(context.Context) (anything, EventContext, error) * func(context.Context, anything) * func(context.Context, anything) error * func(context.Context, anything) (anything, error) * func(context.Context, anything) (anything, EventContext, error)

CloudEvent contexts are available from the context.Context parameter CloudEvent data will be deserialized into the "anything" parameter. The library supports native decoding with both XML and JSON encoding. To accept another advanced type, pass an io.Reader as the input parameter.

HTTP responses are generated based on the return value of fn:

  • any error return value will cause a StatusInternalServerError response
  • a function with no return type or a function returning nil will cause a StatusNoContent response
  • a function that returns a value will cause a StatusOK and render the response as JSON, with headers from an EventContext, if appropriate

func NewRequest

func NewRequest(urlString string, data interface{}, context SendContext) (*http.Request, error)

NewRequest craetes an HTTP request for Structured content encoding.

Types

type BinaryLoader

type BinaryLoader interface {
	// FromHeaders copies data from the supplied HTTP headers into the object.
	// Values will be defaulted if necessary.
	FromHeaders(in http.Header) error
}

BinaryLoader implements an interface for translating a binary encoding HTTP request or response to a an EventContext (possibly one of several versions).

type BinarySender

type BinarySender interface {
	// AsHeaders converts this EventContext to a set of HTTP headers.
	AsHeaders() (http.Header, error)
}

BinarySender implements an interface for sending an EventContext as (possibly one of several versions) as a binary encoding HTTP request.

type Builder

type Builder struct {
	// A URI describing the event producer.
	Source string
	// Type of occurrence which has happened.
	EventType string
	// The version of the `eventType`; this is producer-specific.
	EventTypeVersion string
	// A link to the schema that the `data` attribute adheres to.
	SchemaURL string
	// Additional metadata without a well-defined structure.
	Extensions map[string]interface{}

	// Encoding specifies the requested output encoding of the CloudEvent.
	Encoding CloudEventEncoding
}

Builder holds settings that do not change over CloudEvents. It is intended to represent a builder of only a single CloudEvent type.

func (*Builder) Build

func (b *Builder) Build(target string, data interface{}, overrides ...SendContext) (*http.Request, error)

Build produces a http request with the constant data embedded in the builder merged with the new data provided in the build function. The request will send a pre-assembled cloud event to the given target. The target is assumed to be a URL with a scheme, ie: "http://localhost:8080"

type Client

type Client struct {
	Target string
	// contains filtered or unexported fields
}

Client wraps Builder, and is intended to be configured for a single event type and target

func NewClient

func NewClient(target string, builder Builder) *Client

NewClient returns a CloudEvent Client used to send CloudEvents. It is intended that a user would create a new client for each tuple of eventType and target. This is an optional helper method to avoid the tricky creation of the embedded Builder struct.

func (*Client) Send

func (c *Client) Send(data interface{}, overrides ...SendContext) error

Send creates a request based on the client's settings and sends the data struct to the target set for this client. It returns error if there was an issue sending the event, otherwise nil means the event was accepted.

type CloudEventEncoding

type CloudEventEncoding int

CloudEventEncoding is used to tell the builder which encoding to select. the default is Binary.

const (
	// Binary v0.1
	BinaryV01 CloudEventEncoding = iota
	// Structured v0.1
	StructuredV01
)

type ContextTranslator

type ContextTranslator interface {
	// AsV01 provides a translation from whatever the "native" encoding of the
	// CloudEvent was to the equivalent in v0.1 field names, moving fields to or
	// from extensions as necessary.
	AsV01() V01EventContext

	// AsV02 provides a translation from whatever the "native" encoding of the
	// CloudEvent was to the equivalent in v0.2 field names, moving fields to or
	// from extensions as necessary.
	AsV02() V02EventContext

	// DataContentType returns the MIME content type for encoding data, which is
	// needed by both encoding and decoding.
	DataContentType() string
}

ContextTranslator provides a set of translation methods between the different versions of the CloudEvents spec, which allows programs to interoperate with different versions of the CloudEvents spec by converting EventContexts to their preferred version.

type ContextType

ContextType is a unified interface for both sending and loading the CloudEvent data across versions.

type EventContext

type EventContext = V01EventContext

EventContext is a legacy un-versioned alias, from when we thought that field names would stay the same.

type HTTPMarshaller

type HTTPMarshaller interface {
	FromRequest(data interface{}, r *http.Request) (LoadContext, error)
	NewRequest(urlString string, data interface{}, context SendContext) (*http.Request, error)
}

HTTPMarshaller implements a scheme for decoding CloudEvents over HTTP. Implementations are Binary, Structured, and Any

type LoadContext

type LoadContext interface {
	ContextTranslator

	StructuredLoader
	BinaryLoader
}

LoadContext provides an interface for extracting information from an EventContext (the set of non-data event attributes of a CloudEvent).

func FromContext

func FromContext(ctx context.Context) LoadContext

FromContext loads an V01EventContext from a normal context.Context

func FromRequest

func FromRequest(data interface{}, r *http.Request) (LoadContext, error)

FromRequest parses a CloudEvent from any known encoding.

type Mux

type Mux map[string]*handler

Mux allows developers to handle logically related groups of functionality multiplexed based on the event type. TODO: Consider dropping Mux or figure out how to handle non-JSON encoding.

func NewMux

func NewMux() Mux

NewMux creates a new Mux

func (Mux) Handle

func (m Mux) Handle(eventType string, fn interface{}) error

Handle adds a new handler for a specific event type If the fn parameter is not a valid type, the endpoint will respond to all HTTP requests with that error. Valid types of fn are:

* func() * func() error * func() (anything, error) * func(context.Context) * func(context.Context) error * func(context.Context) (anything, error) * func(context.Context, anything) * func(context.Context, anything) error * func(context.Context, anything) (anything, error)

CloudEvent contexts are available from the context.Context parameter CloudEvent data will be deserialized into the "anything" parameter. The library supports native decoding with both XML and JSON encoding. To accept another advanced type, pass an io.Reader as the input parameter.

HTTP responses are generated based on the return value of fn: * any error return value will cause a StatusInternalServerError response * a function with no return type or a function returning nil will cause a StatusNoContent response * a function that returns a value will cause a StatusOK and render the response as JSON

func (Mux) ServeHTTP

func (m Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler

type SendContext

type SendContext interface {
	ContextTranslator

	StructuredSender
	BinarySender
}

SendContext provides an interface for extracting information from an EventContext (the set of non-data event attributes of a CloudEvent).

type StructuredLoader

type StructuredLoader interface {
	// FromJSON assumes that the object has already been decoded into a raw map
	// from string to json.RawMessage, because this is needed to extract the
	// CloudEvents version.
	FromJSON(map[string]json.RawMessage) error
}

StructuredLoader implements an interface for translating a structured encoding HTTP request or response to a an EventContext (possibly one of several versions).

type StructuredSender

type StructuredSender interface {
	// AsJSON encodes the object into a map from string to JSON data, which
	// allows additional keys to be encoded later.
	AsJSON() (map[string]json.RawMessage, error)
}

StructuredSender implements an interface for translating an EventContext (possibly one of severals versions) to a structured encoding HTTP request.

type V01EventContext

type V01EventContext struct {
	// The version of the CloudEvents specification used by the event.
	CloudEventsVersion string `json:"cloudEventsVersion,omitempty"`
	// ID of the event; must be non-empty and unique within the scope of the producer.
	EventID string `json:"eventID"`
	// Timestamp when the event happened.
	EventTime time.Time `json:"eventTime,omitempty"`
	// Type of occurrence which has happened.
	EventType string `json:"eventType"`
	// The version of the `eventType`; this is producer-specific.
	EventTypeVersion string `json:"eventTypeVersion,omitempty"`
	// A link to the schema that the `data` attribute adheres to.
	SchemaURL string `json:"schemaURL,omitempty"`
	// A MIME (RFC 2046) string describing the media type of `data`.
	// TODO: Should an empty string assume `application/json`, or auto-detect the content?
	ContentType string `json:"contentType,omitempty"`
	// A URI describing the event producer.
	Source string `json:"source"`
	// Additional metadata without a well-defined structure.
	Extensions map[string]interface{} `json:"extensions,omitempty"`
}

V01EventContext holds standard metadata about an event. See https://github.com/cloudevents/spec/blob/v0.1/spec.md#context-attributes for details on these fields.

func (V01EventContext) AsHeaders

func (ec V01EventContext) AsHeaders() (http.Header, error)

AsHeaders implements the BinarySender interface.

func (V01EventContext) AsJSON

func (ec V01EventContext) AsJSON() (map[string]json.RawMessage, error)

AsJSON implements the StructuredSender interface.

func (V01EventContext) AsV01

func (ec V01EventContext) AsV01() V01EventContext

AsV01 implements the ContextTranslator interface.

func (V01EventContext) AsV02

func (ec V01EventContext) AsV02() V02EventContext

AsV02 implements the ContextTranslator interface.

func (V01EventContext) DataContentType

func (ec V01EventContext) DataContentType() string

DataContentType implements the StructuredSender interface.

func (*V01EventContext) FromHeaders

func (ec *V01EventContext) FromHeaders(in http.Header) error

FromHeaders implements the BinaryLoader interface.

func (*V01EventContext) FromJSON

func (ec *V01EventContext) FromJSON(in map[string]json.RawMessage) error

FromJSON implements the StructuredLoader interface.

type V02EventContext

type V02EventContext struct {
	// The version of the CloudEvents specification used by the event.
	SpecVersion string `json:"specversion"`
	// The type of the occurrence which has happened.
	Type string `json:"type"`
	// A URI describing the event producer.
	Source string `json:"source"`
	// ID of the event; must be non-empty and unique within the scope of the producer.
	ID string `json:"id"`
	// Timestamp when the event happened.
	Time time.Time `json:"time,omitempty"`
	// A link to the schema that the `data` attribute adheres to.
	SchemaURL string `json:"schemaurl,omitempty"`
	// A MIME (RFC2046) string describing the media type of `data`.
	// TODO: Should an empty string assume `application/json`, `application/octet-stream`, or auto-detect the content?
	ContentType string `json:"contenttype,omitempty"`
	// Additional extension metadata beyond the base spec.
	Extensions map[string]interface{} `json:"-,omitempty"`
}

V02EventContext represents the non-data attributes of a CloudEvents v0.2 event.

func (V02EventContext) AsHeaders

func (ec V02EventContext) AsHeaders() (http.Header, error)

AsHeaders implements the BinarySender interface.

func (V02EventContext) AsJSON

func (ec V02EventContext) AsJSON() (map[string]json.RawMessage, error)

AsJSON implementsn the StructuredSender interface.

func (V02EventContext) AsV01

func (ec V02EventContext) AsV01() V01EventContext

AsV01 implements the ContextTranslator interface.

func (V02EventContext) AsV02

func (ec V02EventContext) AsV02() V02EventContext

AsV02 implements the ContextTranslator interface.

func (V02EventContext) DataContentType

func (ec V02EventContext) DataContentType() string

DataContentType implements the StructuredSender interface.

func (*V02EventContext) FromHeaders

func (ec *V02EventContext) FromHeaders(in http.Header) error

FromHeaders implements the BinaryLoader interface.

func (*V02EventContext) FromJSON

func (ec *V02EventContext) FromJSON(in map[string]json.RawMessage) error

FromJSON implements the StructuredLoader interface.

Jump to

Keyboard shortcuts

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