resource

package
v0.0.0-...-11eb462 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2023 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

resource is a package for working with external data which may be updated as the program is running.

Index

Constants

View Source
const (
	// Unconditional means that the resource must be fetched regardless if it has changed.
	Unconditional = false

	// Conditional means that the resource must be fetched only if it has changed.
	Conditional = true
)
View Source
const HTTPTimestampFormat = "Mon, 02 Jan 2006 15:04:05 GMT"

Time format expected by e.g. the Last-Modified or If-Modified-Since headers

Variables

View Source
var ErrHTTPNoLastModified = errors.New("server did not return the Last-Modified header")

Returned by HTTP.Fetch if the response is missing the Last-Modified header.

Functions

This section is empty.

Types

type File

type File struct {
	// Open opens the resource file and must behave like [fs.FS]'s Open.
	Open func() (fs.File, error)

	// Clock is the interface used to provide the fetchTime.
	// In nil, [clock.SystemClock] will be used.
	Clock clock.Interface
	// contains filtered or unexported fields
}

File is a resource which supports the fs.File interface.

Files are considered as changed if their modification time (fs.File.Stat().ModTime()) has advanced forward.

&File{Open: ...} is ready to use. See also helper OnFS and Local functions.

func Local

func Local(name string) *File

Local creates a *File resource which calls os.Open(name).

func OnFS

func OnFS(fileSystem fs.FS, name string) *File

OnFS creates a *File resource which calls fileSystem.Open(name).

func (*File) Fetch

func (r *File) Fetch(conditional bool) (content io.ReadCloser, hasChanged bool, err error)

Fetch opens the file, stats it and returns it if either unconditionally is set to true, or the modification time has advanced.

Returned content, if non-nil, will be exactly what Open() has returned.

func (*File) FetchTime

func (r *File) FetchTime() time.Time

FetchTime returns the latest time when Fetch() returned a non-nil content.

func (*File) LastModified

func (r *File) LastModified() time.Time

LastModified returns the modification time of the resource when it was last opened.

type HTTP

type HTTP struct {
	// Request is sent to the server on every call to the FetchIfChanged.
	// The request object is reused between calls - and if the request is supposed to have
	// some body, the GetBody field must be used; not Body.
	//
	// FetchIfChanged will modify 2 headers in the request: If-Modified-Since and If-None-Match.
	Request *http.Request

	// Client is used the object used to actually perform the request.
	// If nil, [http.DefaultClient] will be used.
	Client *http.Client

	// Clock is the interface used to provide the fetchTime.
	// In nil, clock.SystemClock will be used.
	Clock clock.Interface
	// contains filtered or unexported fields
}

HTTP is a resource which lives on a remote HTTP or a HTTPS server.

If the server uses ETags, the resource is considered as changed if their ETag changes. Otherwise, the resource is considered as changed if Last-Modified has advanced.

The server must include the Last-Modified header and must support the If-Modified-Since (and If-None-Match if using ETags).

`&HTTP{Request: request}` is ready to use.

func HTTPGet

func HTTPGet(url string) *HTTP

HTTPGet creates a simple HTTP resource performing GET requests to the specified URL using http.DefaultClient.

The Request and Client may be further customized.

Panics if http.NewRequest fails.

func HTTPGetURL

func HTTPGetURL(url *url.URL) *HTTP

HTTPGetUrl creates a simple HTTP resource performing GET requests to the specified *url.URL using http.DefaultClient.

The Request and Client may be further customized.

Panics if http.NewRequest fails.

func HTTPPost

func HTTPPost(url string, contentType string, body io.Reader) *HTTP

HTTPPost creates a simple HTTP resource performing POST requests to the specified URL using http.DefaultClient. Request.GetBody must be set for the body to be properly replied with every call to [HTTP.FetchIfChanged]; it is automatically set for *bytes.Buffer, *bytes.Reader and *strings.Reader (by http.NewRequestWithContext).

The Request and Client may be further customized.

Panics if http.NewRequest fails.

func HTTPPostForm

func HTTPPostForm(url string, data url.Values) *HTTP

HTTPPostForm creates a simple HTTP resource performing POST requests to the specified url with the specified form using http.DefaultClient.

Content-Type is set to "application/x-www-form-urlencoded" and Request.GetBody is set to return the same data every time.

The Request and Client may be further customized.

Panics if http.NewRequest fails.

func HTTPPostFormURL

func HTTPPostFormURL(url *url.URL, data url.Values) *HTTP

HTTPPostForm creates a simple HTTP resource performing POST requests to the specified *url.URL with the specified form using http.DefaultClient.

Content-Type is set to "application/x-www-form-urlencoded" and Request.GetBody is set to return the same data every time.

The Request and Client may be further customized.

Panics if http.NewRequest fails.

func HTTPPostURL

func HTTPPostURL(url *url.URL, contentType string, body io.Reader) *HTTP

HTTPPost creates a simple HTTP resource performing POST requests to the specified *url.URL using http.DefaultClient. Request.GetBody must be set for the body to be properly replied with every call to [HTTP.FetchIfChanged]; it is automatically set for *bytes.Buffer, *bytes.Reader and *strings.Reader (by http.NewRequestWithContext).

The Request and Client may be further customized.

Panics if http.NewRequest fails.

func (*HTTP) ETag

func (r *HTTP) ETag() string

ETag returns the value of the ETag header as of FetchTime().

func (*HTTP) Fetch

func (r *HTTP) Fetch(conditional bool) (body io.ReadCloser, hasChanged bool, err error)

Fetch tries to fetch the resource.

If the fetch is Unconditional, makes use of the conditional request headers. In this case, the server must reply with 304 Input Not Modified in order for this function to detect that the content has not changed.

If the fetch is Conditional, hasChanged will be set if the ETag has changed (if the server returned one), or it the Last-Modified time has advanced.

On any errors, including 4xx, 5xx and 3xx status codes, (nil, false, err) is returned.

func (*HTTP) FetchTime

func (r *HTTP) FetchTime() time.Time

FetchTime returns the time of the latest fetch which returned a non-nil body.

func (*HTTP) LastModified

func (r *HTTP) LastModified() time.Time

LastModified returns the value of Last-Modified as of FetchTime().

type HTTPError

type HTTPError struct {
	Request  *http.Request
	Response *http.Response
}

HTTPError is an error returned when a HTTP server returns an unsuccessful response; usually one with status codes 3xx, 4xx or 5xx.

func (HTTPError) Error

func (h HTTPError) Error() string

type Interface

type Interface interface {
	// Fetch returns the content of the resource if the resource has changed,
	// or the fetch is Unconditional.
	//
	// If an error occurs, (nil, false, err) is returned.
	//
	// For Conditional fetches, the hasChanged return value can be ignored -
	// if the resource changed, returns its content; nil if the resource has not changed.
	//
	// For Unconditional fetches, the content is always non-nil, and the hasChanged
	// flag is set appropriately.
	Fetch(conditional bool) (content io.ReadCloser, hasChanged bool, err error)

	// FetchTime returns the time when the resource was successfully fetched.
	FetchTime() time.Time

	// LastModified returns the time when the external resource was changed as of FetchTime().
	LastModified() time.Time
}

Interface represents an external resource, which may change as the program is running.

type TimeLimited

type TimeLimited struct {
	R                  Interface
	MinimalTimeBetween time.Duration

	// Clock is the interface used to provide time - to decide when to fetch
	// forward the fetches to the underlying resource.
	// In nil, [clock.SystemClock] will be used.
	Clock clock.Interface
	// contains filtered or unexported fields
}

TimeLimited is a simple rate-limiting mechanizm for Resources - ensures R.Fetch() is called when at least MinimalTimeBetween has passed.

func (*TimeLimited) Fetch

func (t *TimeLimited) Fetch(conditional bool) (content io.ReadCloser, hasChanged bool, err error)

Fetch forwards the call to R.Fetch(conditional) only if it is time to check the resource (see [TimeLimited.ShouldCheck]) or the fetch is Unconditional.

func (*TimeLimited) FetchTime

func (t *TimeLimited) FetchTime() time.Time

FetchTime returns the last time the resource was actually fetched; alias for t.R.FetchTime().

func (*TimeLimited) LastCheck

func (t *TimeLimited) LastCheck() time.Time

LastCheck returns the time when the resource was last checked, or a zero-value time.Time if the resource was never checked.

func (*TimeLimited) LastModified

func (t *TimeLimited) LastModified() time.Time

FetchTime returns the last time the resource was last modified (as of FetchTime()); alias for t.R.LastModified().

func (*TimeLimited) NextCheck

func (t *TimeLimited) NextCheck() time.Time

NextCheck returns the time when the resource should be checked, or a zero-value time.Time if the resource was never checked.

Jump to

Keyboard shortcuts

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