httpbasic

package
v0.0.0-...-f61c53a Latest Latest
Warning

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

Go to latest
Published: Nov 18, 2025 License: MIT Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// ConnectionIDHeader is intended for linking return channels to requests.
	// intended for separated return channel like sse.
	ConnectionIDHeader = "cid"
	// CorrelationIDHeader is the header to be able to link requests to out of band responses
	// tentative as it isn't part of the wot spec
	CorrelationIDHeader = "correlationID"

	// HttpPostLoginPath is the fixed authentication endpoint of the hub
	HttpPostLoginPath   = "/authn/login"
	HttpPostLogoutPath  = "/authn/logout"
	HttpPostRefreshPath = "/authn/refresh"
	HttpGetPingPath     = "/ping"

	// The generic path for thing operations over http using URI variables
	HttpBaseFormOp                   = "/things"
	HttpBasicAffordanceOperationPath = "/things/{operation}/{thingID}/{name}"
	HttpBasicThingOperationPath      = "/things/{operation}/{thingID}"
	HttpBasicOperationURIVar         = "operation"
	HttpBasicThingIDURIVar           = "thingID"
	HttpBasicNameURIVar              = "name"

	// static file server routes
	DefaultHttpStaticBase      = "/static"
	DefaultHttpStaticDirectory = "stores/httpstatic" // relative to home
)

HTTP-basic profile constants

View Source
const ContextClientID = "clientID"
View Source
const SessionContextID = "session"

Variables

Functions

func AddSessionFromToken

func AddSessionFromToken(userAuthn messaging.IAuthenticator) func(next http.Handler) http.Handler

AddSessionFromToken middleware decodes the bearer session token in the authorization header.

Session tokens can be provided through a bearer token or a client cookie. The token must match with an existing session ID.

This distinguishes two types of tokens. Those with and those without a session ID. If the token contains a session ID then that session must exist or the token is invalid. User tokens are typically session tokens. Closing the session (logout) invalidates the token, even if it hasn't yet expired. Sessions are currently only stored in memory so a service restart also invalidates all session tokens.

Non-session tokens, are used by services and device agents. These tokens are generated on provisioning or token renewal and last until their expiry.

The session can be retrieved from the request context using GetSessionFromContext()

The client session contains the client ID, and stats for the current session. If no valid session is found this will reply with an unauthorized status code.

pubKey is the public key from the keypair used in creating the session token.

func GetClientIdFromContext

func GetClientIdFromContext(r *http.Request) (clientID string, err error)

GetClientIdFromContext returns the authenticated clientID for the given request

Types

type HttpActionStatusMessage

type HttpActionStatusMessage struct {
	// Status is one of "pending","running","completed" or "failed"
	Status string `json:"status,omitempty"`

	Output any `json:"output,omitempty"`

	//Error message, if any, containing problem details format (RF7807)
	// For now just text
	Error string `json:"error,omitempty"`

	// The [URL] of an HttpActionStatus resource which can be used by queryaction
	// and cancelaction operations
	Href string `json:"href,omitempty"`

	// A timestamp indicating the time at which the Thing received the request
	// to execute the action.
	TimeRequested string `json:"timeRequested,omitempty"`

	//A timestamp indicating the time at which the Thing successfully completed
	//executing the action, or failed to execute the action.
	TimeEnded string `json:"timeEnded,omitempty"`
}

HttpActionStatusMessage the status of an asynchronous action invocation request

type HttpBasicServer

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

HttpBasicServer provides the http-basic protocol binding using the provided http server. This is the simplest protocol binding supported by hiveot. Features: - security bootstrapping as per https://w3c.github.io/wot-discovery/#exploration-secboot

  • login to obtain a bearer token: POST {base}/authn/login
  • refresh bearer token: POST {base}/authn/refresh

- post/get thing operations: POST {base}/things/{op}/{thingID} - post/get affordance operations: POST {base}/things/{op}/{thingID}/{name}

This uses the provided httpserver instance.

func NewHttpBasicServer

func NewHttpBasicServer(
	connectAddr string,
	router *chi.Mux,
	authenticator messaging.IAuthenticator,

	handleNotification messaging.NotificationHandler,
	handleRequest messaging.RequestHandler,
	handleResponse messaging.ResponseHandler,
) *HttpBasicServer

NewHttpBasicServer creates a new http-basic protocol binding. Intended for use as server for sub-protocols such as sse and wss.

connectAddr is the host:port the server can be reached at.
router is the router to register paths at.

On startup this creates a public and protected route. Protected routes can be registered by sub-protocols. This http-basic handles the connection authentication.

func (*HttpBasicServer) AddAffordanceForms

func (srv *HttpBasicServer) AddAffordanceForms(tdoc *td.TD)

AddAffordanceForms adds forms to affordances for interacting using the websocket protocol binding http-basic only supports read-write

func (*HttpBasicServer) AddTDForms

func (srv *HttpBasicServer) AddTDForms(tdoc *td.TD, includeAffordances bool)

AddTDForms sets the forms for use of http-basic to the given TD.

This sets the base to the http connect URL and uses relative hrefs for the forms. The href MUST match the route defined in: HttpBasicRoutes.HttpBasicAffordanceOperationPath e.g.: "https://host:port/things/{op}/{thingID}/{name}"

As content-Type is the default application/json it is omitted.

If the method names for get operations is default GET then it is omitted from the form.

includeAffordances adds forms for all affordances to be compliant with the specifications.

func (*HttpBasicServer) CloseAll

func (srv *HttpBasicServer) CloseAll()

CloseAll does nothing as http is connectionless.

func (*HttpBasicServer) CloseAllClientConnections

func (srv *HttpBasicServer) CloseAllClientConnections(clientID string)

CloseAllClientConnections does nothing as http is connectionless.

func (*HttpBasicServer) EnableStatic

func (srv *HttpBasicServer) EnableStatic(base string, staticRoot string) error

EnableStatic adds a path to read files from the static directory. Auth required.

base is the base path on which to serve the static files, eg: "/static"
staticRoot is the root directory where static files are kept. This must be a full path.

func (*HttpBasicServer) GetAuthServerURI

func (srv *HttpBasicServer) GetAuthServerURI() string

GetAuthServerURI returns the URI of the authentication server to include in the TD security scheme FIXME: Should this be some kind of authorization flow with a web page? This is currently just the login endpoint (post /authn/login). The http server might need to include a web page where users can enter their login name and password, although that won't work for machines... tbd

Note that web browsers do not directly access the runtime endpoints. Instead a web server (hiveoview or other) provides the user interface. Including the auth endpoint here is currently just a hint. How to integrate this?

func (*HttpBasicServer) GetConnectURL

func (srv *HttpBasicServer) GetConnectURL() string

GetConnectURL returns connection url of the http server

func (*HttpBasicServer) GetConnectionByClientID

func (srv *HttpBasicServer) GetConnectionByClientID(agentID string) messaging.IConnection

GetConnectionByClientID returns returns nil as http-basic is connectionless

func (*HttpBasicServer) GetConnectionByConnectionID

func (srv *HttpBasicServer) GetConnectionByConnectionID(clientID, cid string) messaging.IConnection

GetConnectionByConnectionID returns nil as http-basic is connectionless

func (*HttpBasicServer) GetForm

func (srv *HttpBasicServer) GetForm(operation string, thingID string, name string) *td.Form

GetForm returns a form for the given operation

func (*HttpBasicServer) GetProtectedRouter

func (srv *HttpBasicServer) GetProtectedRouter() chi.Router

GetProtectedRouter return the router for adding protected paths. Protected means the client is authenticated.

func (*HttpBasicServer) GetProtocolType

func (srv *HttpBasicServer) GetProtocolType() string

func (*HttpBasicServer) GetPublicRouter

func (srv *HttpBasicServer) GetPublicRouter() chi.Router

GetPublicRouter return the router for adding public paths.

func (*HttpBasicServer) HandleAuthRefresh

func (srv *HttpBasicServer) HandleAuthRefresh(w http.ResponseWriter, r *http.Request)

HandleAuthRefresh refreshes the auth token using the session authenticator. The session authenticator is that of the authn service. This allows testing with a dummy authenticator without having to run the authn service.

func (*HttpBasicServer) HandleLogin

func (srv *HttpBasicServer) HandleLogin(w http.ResponseWriter, r *http.Request)

HandleLogin handles a login request and returns an auth token.

Body contains {"login":name, "password":pass} format This is the only unprotected route supported. This uses the configured session authenticator.

func (*HttpBasicServer) HandleLogout

func (srv *HttpBasicServer) HandleLogout(w http.ResponseWriter, r *http.Request)

HandleLogout ends the session and closes all client connections

func (*HttpBasicServer) HandlePing

func (srv *HttpBasicServer) HandlePing(w http.ResponseWriter, r *http.Request)

HandlePing with http handler returns a pong response

func (*HttpBasicServer) SendNotification

func (srv *HttpBasicServer) SendNotification(msg *messaging.NotificationMessage)

SendNotification does nothing as http-basic is connectionless

func (*HttpBasicServer) Start

func (srv *HttpBasicServer) Start() error

Start listening on the routes

func (*HttpBasicServer) Stop

func (srv *HttpBasicServer) Stop()

type HttpErrorResponse

type HttpErrorResponse struct {
	// URI reference identifying the problem type
	// Not sure what to put in here. Problem types don't exist in URI format.
	Type string `json:"type,omitempty"`
	// Human readable short summary
	Title string `json:"title"`
	// HTTP status code generated by the origin server
	// Likely 403 (no auth
	Status   int    `json:"status.omitempty"`
	Detail   string `json:"detail,omitempty"`   // Detail of the error
	Instance string `json:"instance,omitempty"` // Resource that identifies the occurrance of the problem
}

https://w3c.github.io/wot-profile/#error-responses If an HTTP error response contains a body, the content of that body MUST conform with the Problem Details format [RFC7807]. https://www.rfc-editor.org/rfc/rfc7807#section-3

type RequestParams

type RequestParams struct {
	ClientID      string // authenticated client ID
	ThingID       string // the thing ID if defined in the URL as {thingID}
	CorrelationID string // tentative as it isn't in the spec
	Name          string // the affordance name if defined in the URL as {name}
	ConnectionID  string // connectionID as provided by the client
	Op            string // the operation if defined in the URL as {op}
	Payload       []byte // the raw request payload (body)
}

RequestParams contains the parameters read from the HTTP request

func GetRequestParams

func GetRequestParams(r *http.Request) (reqParam RequestParams, err error)

GetRequestParams reads the client session, URL parameters and body payload from the http request context.

The session context is set by the http middleware. If the session is not available then this returns an error. Note that the session middleware handler will block any request that requires a session.

This protocol binding determines three variables, {thingID}, {name} and {op} from the path. It unmarshal's the request body into 'data', if given.

{operation} is the operation
{thingID} is the agent or digital twin thing ID
{name} is the property, event or action name. '+' means 'all'

func (*RequestParams) Unmarshal

func (rp *RequestParams) Unmarshal(data any) error

Convenience function to unmarshal the payload into the given data struct If no payload is available this does nothing and data remains unchanged

type StaticFSWrapper

type StaticFSWrapper struct {
	http.FileSystem
	FixedModTime time.Time
}

StaticFSWrapper adds a timestamp to files from embed. Without it, static files have the current time, causing cache-control to fail. From: https://github.com/golang/go/issues/44854

func (*StaticFSWrapper) Open

func (f *StaticFSWrapper) Open(name string) (http.File, error)

type StaticFileInfoWrapper

type StaticFileInfoWrapper struct {
	os.FileInfo
	// contains filtered or unexported fields
}

func (*StaticFileInfoWrapper) ModTime

func (f *StaticFileInfoWrapper) ModTime() time.Time

type StaticFileWrapper

type StaticFileWrapper struct {
	http.File
	// contains filtered or unexported fields
}

func (*StaticFileWrapper) Stat

func (f *StaticFileWrapper) Stat() (os.FileInfo, error)

Jump to

Keyboard shortcuts

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