package httprange
Import Path
go.pact.im/x/httprange (on go.dev)
Dependency Relation
imports 16 packages, and imported by 0 packages
Involved Source Files
builder.go
bytes.go
contentrange.go
Package httprange implements io.ReaderAt interface for HTTP range requests as
specified in RFC 7233 and RFC 9110.
errors.go
gen.go
metadata.go
ranger.go
request.go
resource.go
validator.go
Code Examples
package main
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"time"
"go.pact.im/x/httprange"
)
type handlerTransport struct {
handler http.Handler
}
func (t *handlerTransport) RoundTrip(r *http.Request) (*http.Response, error) {
w := httptest.NewRecorder()
t.handler.ServeHTTP(w, r)
return w.Result(), nil
}
func newClient(handler http.HandlerFunc) *http.Client {
return &http.Client{
Transport: &handlerTransport{
handler: handler,
},
}
}
func main() {
client := newClient(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Etag", `"512aedef7775096f9e152526a30a0ce7"`)
http.ServeContent(w, r,
"shakespeare.txt",
time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Second),
bytes.NewReader([]byte("To be, or not to be, that is the question.")),
)
})
ctx := context.Background()
resource, err := httprange.BuildFromRawURL(ctx, "https://example.com", client)
if err != nil {
panic(err)
}
reader := resource.Reader(ctx)
defer func() {
_ = reader.Close()
}()
buf1 := make([]byte, 5)
n, err := reader.ReadAt(buf1, 0)
if err != nil {
panic(err)
}
fmt.Println("Bytes 0-4:", string(buf1[:n]))
buf2 := make([]byte, 12)
n, err = reader.ReadAt(buf2, 7)
if err != nil {
panic(err)
}
fmt.Println("Bytes 7-18:", string(buf2[:n]))
buf3 := make([]byte, 42)
n, err = reader.ReadAt(buf3, 41)
if err != io.EOF {
panic(err)
}
fmt.Println("Bytes 41-41:", string(buf3[:n]))
}
Package-Level Type Names (total 28, in which 25 are exported)
Builder constructs a [BytesResource] for an HTTP resource that supports byte
range requests.
Client is the HTTP client instance to use.
Metadata extracts representation metadata for the resource.
Request builds the HTTP GET request for range requests.
Validator builds a validator for conditional requests.
Build creates a [BytesResource] for the configured HTTP resource.
func NewBuilderFromURL(u *url.URL, client httpclient.Client) *Builder
BytesReader implements [io.ReaderAt] for reading byte ranges from a [Ranger].
Context is the context to use for Ranger.Range calls.
Ranger is the Ranger instance for performing range requests.
ReadAt reads len(p) bytes starting at byte offset off. It performs a byte
range request for the range [off, off+len(p)-1] and reads the response into
p. It returns [io.EOF] if the range cannot be satisfied.
*BytesReader : io.ReaderAt
BytesResource represents a resource with a known length that supports byte
range requests.
Length is the complete length of the resource in bytes.
Ranger is the Ranger instance for performing range requests.
Reader returns a [BytesResourceReader] for reading the resource.
The provided context controls the lifetime of the reader; canceling it will
abort any in-flight range requests.
The returned reader must be closed after use by calling its Close method.
func BuildFromRawURL(ctx context.Context, rawURL string, client httpclient.Client) (*BytesResource, error)
func (*Builder).Build(ctx context.Context) (*BytesResource, error)
BytesResourceReader provides sequential and random access to a [BytesResource].
It implements [io.ReaderAt], [io.Reader], [io.Seeker], and [io.Closer].
Cancel is a function that cancels reads.
Length is the complete length of the resource in bytes.
Offset is the current offset for reading and seeking.
// mutable
Reader is the underlying resource reader.
Close releases resources associated with the reader and cancels any pending
range requests with [BytesResourceReaderClosedError] cause.
After Close returns, all subsequent operations on the reader will fail.
Read reads up to len(p) bytes into p.
ReadAt reads len(p) bytes from offset off into p.
Seek sets the offset for the next read.
(*BytesResourceReader) slice(p []byte, off int64) ([]byte, bool)
*BytesResourceReader : io.Closer
*BytesResourceReader : io.ReadCloser
*BytesResourceReader : io.Reader
*BytesResourceReader : io.ReaderAt
*BytesResourceReader : io.ReadSeekCloser
*BytesResourceReader : io.ReadSeeker
*BytesResourceReader : io.Seeker
*BytesResourceReader : mime/multipart.File
func (*BytesResource).Reader(ctx context.Context) *BytesResourceReader
BytesResourceReaderClosedError indicates that [BytesResourceReader] was closed.
Error returns the error message. It implements the [error] interface.
*BytesResourceReaderClosedError : error
var errBytesResourceReaderClosed *BytesResourceReaderClosedError
HTTPMetadata contains representation metadata for a resource.
AcceptRanges contains advertised Accept-Ranges header values.
ContentLength is the complete length of the representation in bytes.
Date is the server date when the metadata was retrieved.
ETag is the current representation entity tag.
LastModified is the last modification time.
Provide implements the [HTTPMetadataProvider] interface.
*HTTPMetadata : HTTPMetadataProvider
func (*HTTPMetadata).Provide() *HTTPMetadata
func HTTPMetadataProvider.Provide() *HTTPMetadata
func extractHTTPResponseMetadata(resp *http.Response) (*HTTPMetadata, error)
HTTPMetadataExtractor extracts representation metadata for a resource.
Extract retrieves metadata for the resource. It returns the metadata
or an error if the extraction fails.
*HTTPResponseMetadataExtractor
HTTPMetadataProvider provides representation metadata for a resource.
( HTTPMetadataProvider) Provide() *HTTPMetadata
*HTTPMetadata
func HTTPMetadataExtractor.Extract(context.Context) (HTTPMetadataProvider, error)
func (*HTTPResponseMetadataExtractor).Extract(ctx context.Context) (HTTPMetadataProvider, error)
func (*HTTPStrongValidatorBuilder).Build(_ context.Context, mp HTTPMetadataProvider, client httpclient.Client) (httpclient.Client, error)
func HTTPValidatorBuilder.Build(context.Context, HTTPMetadataProvider, httpclient.Client) (httpclient.Client, error)
HTTPRanger implements the [Ranger] interface for HTTP resources.
Client is the HTTP client instance to use.
Request is a builder for HTTP HEAD request that is used to retrieve
representation metadata.
Range performs a range request for the given specifier. It sends an HTTP
request with a Range header and returns an iterator over the ranges in the
response (a single range or a multipart/byteranges parts).
*HTTPRanger : Ranger
HTTPRequest is an [HTTPRequestBuilder] implementation that wraps an existing
[http.Request].
Body is the request's body.
For client requests, a nil body means the request has no
body, such as a GET request. The HTTP Client's Transport
is responsible for calling the Close method.
For server requests, the Request Body is always non-nil
but will return EOF immediately when no body is present.
The Server will close the request body. The ServeHTTP
Handler does not need to.
Body must allow Read to be called concurrently with Close.
In particular, calling Close should unblock a Read waiting
for input.
Cancel is an optional channel whose closure indicates that the client
request should be regarded as canceled. Not all implementations of
RoundTripper may support Cancel.
For server requests, this field is not applicable.
Deprecated: Set the Request's context with NewRequestWithContext
instead. If a Request's Cancel field and context are both
set, it is undefined whether Cancel is respected.
Close indicates whether to close the connection after
replying to this request (for servers) or after sending this
request and reading its response (for clients).
For server requests, the HTTP server handles this automatically
and this field is not needed by Handlers.
For client requests, setting this field prevents re-use of
TCP connections between requests to the same hosts, as if
Transport.DisableKeepAlives were set.
ContentLength records the length of the associated content.
The value -1 indicates that the length is unknown.
Values >= 0 indicate that the given number of bytes may
be read from Body.
For client requests, a value of 0 with a non-nil Body is
also treated as unknown.
Form contains the parsed form data, including both the URL
field's query parameters and the PATCH, POST, or PUT form data.
This field is only available after ParseForm is called.
The HTTP client ignores Form and uses Body instead.
GetBody defines an optional func to return a new copy of
Body. It is used for client requests when a redirect requires
reading the body more than once. Use of GetBody still
requires setting Body.
For server requests, it is unused.
Header contains the request header fields either received
by the server or to be sent by the client.
If a server received a request with header lines,
Host: example.com
accept-encoding: gzip, deflate
Accept-Language: en-us
fOO: Bar
foo: two
then
Header = map[string][]string{
"Accept-Encoding": {"gzip, deflate"},
"Accept-Language": {"en-us"},
"Foo": {"Bar", "two"},
}
For incoming requests, the Host header is promoted to the
Request.Host field and removed from the Header map.
HTTP defines that header names are case-insensitive. The
request parser implements this by using CanonicalHeaderKey,
making the first character and any characters following a
hyphen uppercase and the rest lowercase.
For client requests, certain headers such as Content-Length
and Connection are automatically written when needed and
values in Header may be ignored. See the documentation
for the Request.Write method.
For server requests, Host specifies the host on which the
URL is sought. For HTTP/1 (per RFC 7230, section 5.4), this
is either the value of the "Host" header or the host name
given in the URL itself. For HTTP/2, it is the value of the
":authority" pseudo-header field.
It may be of the form "host:port". For international domain
names, Host may be in Punycode or Unicode form. Use
golang.org/x/net/idna to convert it to either format if
needed.
To prevent DNS rebinding attacks, server Handlers should
validate that the Host header has a value for which the
Handler considers itself authoritative. The included
ServeMux supports patterns registered to particular host
names and thus protects its registered Handlers.
For client requests, Host optionally overrides the Host
header to send. If empty, the Request.Write method uses
the value of URL.Host. Host may contain an international
domain name.
Method specifies the HTTP method (GET, POST, PUT, etc.).
For client requests, an empty string means GET.
MultipartForm is the parsed multipart form, including file uploads.
This field is only available after ParseMultipartForm is called.
The HTTP client ignores MultipartForm and uses Body instead.
Pattern is the [ServeMux] pattern that matched the request.
It is empty if the request was not matched against a pattern.
PostForm contains the parsed form data from PATCH, POST
or PUT body parameters.
This field is only available after ParseForm is called.
The HTTP client ignores PostForm and uses Body instead.
The protocol version for incoming server requests.
For client requests, these fields are ignored. The HTTP
client code always uses either HTTP/1.1 or HTTP/2.
See the docs on Transport for details.
// "HTTP/1.0"
// 1
// 0
RemoteAddr allows HTTP servers and other software to record
the network address that sent the request, usually for
logging. This field is not filled in by ReadRequest and
has no defined format. The HTTP server in this package
sets RemoteAddr to an "IP:port" address before invoking a
handler.
This field is ignored by the HTTP client.
RequestURI is the unmodified request-target of the
Request-Line (RFC 7230, Section 3.1.1) as sent by the client
to a server. Usually the URL field should be used instead.
It is an error to set this field in an HTTP client request.
Response is the redirect response which caused this request
to be created. This field is only populated during client
redirects.
TLS allows HTTP servers and other software to record
information about the TLS connection on which the request
was received. This field is not filled in by ReadRequest.
The HTTP server in this package sets the field for
TLS-enabled connections before invoking a handler;
otherwise it leaves the field nil.
This field is ignored by the HTTP client.
Trailer specifies additional headers that are sent after the request
body.
For server requests, the Trailer map initially contains only the
trailer keys, with nil values. (The client declares which trailers it
will later send.) While the handler is reading from Body, it must
not reference Trailer. After reading from Body returns EOF, Trailer
can be read again and will contain non-nil values, if they were sent
by the client.
For client requests, Trailer must be initialized to a map containing
the trailer keys to later send. The values may be nil or their final
values. The ContentLength must be 0 or -1, to send a chunked request.
After the HTTP request is sent the map values can be updated while
the request body is read. Once the body returns EOF, the caller must
not mutate Trailer.
Few HTTP clients, servers, or proxies support HTTP trailers.
TransferEncoding lists the transfer encodings from outermost to
innermost. An empty list denotes the "identity" encoding.
TransferEncoding can usually be ignored; chunked encoding is
automatically added and removed as necessary when sending and
receiving requests.
URL specifies either the URI being requested (for server
requests) or the URL to access (for client requests).
For server requests, the URL is parsed from the URI
supplied on the Request-Line as stored in RequestURI. For
most requests, fields other than Path and RawQuery will be
empty. (See RFC 7230, Section 5.3)
For client requests, the URL's Host specifies the server to
connect to, while the Request's Host field optionally
specifies the Host header value to send in the HTTP
request.
ctx is either the client or server context. It should only
be modified via copying the whole Request using Clone or WithContext.
It is unexported to prevent people from using Context wrong
and mutating the contexts held by callers of the same request.
// values for the matching wildcards in pat
// for calls to SetPathValue that don't match a wildcard
The following fields are for requests matched by ServeMux.
// the pattern that matched
Build returns a shallow copy of the request with the given context.
It implements the [HTTPRequestBuilder] interface.
*HTTPRequest : HTTPRequestBuilder
HTTPRequestBuilder is a factory for [http.Request] instances.
Build creates a new HTTP request for the given context.
*HTTPRequest
HTTPRequestBuilderFunc
HTTPRequestBuilderFunc is a function that implements [HTTPRequestBuilder]
interface.
Build implements the [HTTPRequestBuilder] interface.
HTTPRequestBuilderFunc : HTTPRequestBuilder
HTTPResponseError wraps an error that occurred while processing an HTTP response.
Response *http.Response
cause error
Error returns the error message. It implements the [error] interface.
Unwrap returns the underlying error.
*HTTPResponseError : error
HTTPResponseMetadataExtractor implements [HTTPMetadataExtractor] by
performing an HTTP HEAD request to retrieve representation metadata.
Client is the HTTP client instance to use.
Request is a builder for HTTP HEAD request that is used to retrieve
representation metadata.
Extract performs a HEAD request and extracts metadata from the response.
*HTTPResponseMetadataExtractor : HTTPMetadataExtractor
HTTPStrongValidator is an [httpclient.Client] that adds precondition headers
to requests and validates that the resource hasn’t changed in responses.
Client is the HTTP client instance to use.
ETag is the expected entity tag in responses.
LastModified is the expected Last-Modified time in responses.
Precondition contains headers to add to requests.
Do executes a conditional HTTP request and checks the response to ensure the
resource hasn’t changed.
(*HTTPStrongValidator) checkValidator(resp *http.Response) error
*HTTPStrongValidator : go.pact.im/x/httpclient.Client
HTTPStrongValidatorBuilder implements [HTTPValidatorBuilder] using strong
validators. It prefers strong ETags over Last-Modified dates for validation.
UseLastModified controls whether to use Last-Modified dates when
no strong ETag is available. When false, returns an error if no
strong ETag is available.
Build creates a validator client that adds either If-Match or If-Unmodified-Since
headers to requests, depending on the available metadata.
It returns an error if no applicable validator is available.
*HTTPStrongValidatorBuilder : HTTPValidatorBuilder
HTTPValidatorBuilder builds HTTP clients that wraps [httpclient.Client] with
resource state validation.
( HTTPValidatorBuilder) Build(context.Context, HTTPMetadataProvider, httpclient.Client) (httpclient.Client, error)
*HTTPStrongValidatorBuilder
NoApplicableValidatorError indicates that the server did not respond with
a validator that can be used for future requests.
Error returns the error message. It implements the [error] interface.
*NoApplicableValidatorError : error
var errNoApplicableValidator *NoApplicableValidatorError
Range represents a single range response.
Reader is the reader for the range content.
Resp is the range specification for the content.
Ranger performs range requests and returns the requested ranges as a sequence.
Range returns a non-empty sequence of ranges for the given specifier.
Iteration yields Range values until an error. The [Range.Reader] is
valid only until the next iteration.
*HTTPRanger
RangesNotSupportedError indicates that the server does not support range
requests (response contains "Accept-Ranges: none" header).
Error returns the error message. It implements the [error] interface.
*RangesNotSupportedError : error
var errRangesNotSupported *RangesNotSupportedError
Specifier represents a Range header value. It consists of a unit and a range
set (e.g. "bytes=0-99,100-200").
Unit returns the unit of the range.
func BytesSpecifier(positions ...int64) Specifier
func (*HTTPRanger).Range(ctx context.Context, spec Specifier) iter.Seq2[Range, error]
func Ranger.Range(ctx context.Context, spec Specifier) iter.Seq2[Range, error]
UnacceptedUnitError indicates that the server does not accept the requested
range unit.
AcceptRanges contains advertised Accept-Ranges header values.
Error returns the error message. It implements the [error] interface.
*UnacceptedUnitError : error
UnexpectedStatusCodeError indicates that the server returned an unexpected
HTTP status code.
Status string
StatusCode int
Error returns the error message. It implements the [error] interface.
*UnexpectedStatusCodeError : error
UnsatisfiedRangeError indicates that the requested range cannot be satisfied.
This corresponds to the HTTP status code 416 (Range Not Satisfiable).
Resp contains unsatisfied range, if provided by the server.
Error returns the error message. It implements the [error] interface.
*UnsatisfiedRangeError : error
Package-Level Functions (total 20, in which 3 are exported)
BuildFromRawURL is a convenience function that builds a [BytesResource] from
the parsed URL. If client is nil, the default HTTP client is used.
BytesSpecifier constructs a byte range specifier from a sequence of positions.
The positions are interpreted as follows:
- An empty sequence produces the unsatisfiable range "-0".
- A negative integer N produces a suffix-range "-N".
- A non-negative integer N followed by a smaller or
negative integer produces an open range "N-".
- Two adjacent non-negative integers M, N where M ≤ N
produce a closed range "M-N".
It preserves input order even if it produces overlapping ranges or ranges are
not strictly in ascending order.
NewBuilderFromURL returns a new [Builder] for the given URL and HTTP client.
If client is nil, the default HTTP client is used.
Package-Level Variables (total 3, none are exported)
Package-Level Constants (total 13, none are exported)
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)