Documentation
¶
Overview ¶
Package rangeparser parses the HTTP Range header, a port of the npm "range-parser" package used by Express for req.range and by static file servers to implement partial-content (HTTP 206) responses. It resolves a Range header such as "bytes=0-499" against a total resource size and reports the concrete byte ranges requested.
The Range header lets a client ask for one or more sub-ranges of a resource instead of the whole thing, which is what makes resumable downloads and media seeking possible. A header has the form "unit=spec,spec,..." where unit is typically "bytes" and each spec is either "start-end", "start-" (from start to the end of the resource), or "-suffix" (the final suffix bytes). Parse resolves each spec against the given size, clamping ends that run past the last byte and translating suffix ranges into absolute [Start, End] offsets.
Both Start and End are inclusive, matching the HTTP specification: a request for "bytes=0-499" against a large resource yields a single Range{Start: 0, End: 499} covering exactly 500 bytes. Specs whose start exceeds their end after clamping are skipped as unsatisfiable, and a suffix larger than the resource is clamped so it begins at offset zero.
The result code distinguishes three outcomes. ResultOK (0) means at least one satisfiable range was produced. ResultUnsatisfiable (-1) means the header was syntactically valid but no spec overlaps the resource, which corresponds to an HTTP 416 response. ResultMalformed (-2) means the header could not be parsed at all: it lacked a "=", used an empty unit, contained a spec with no "-", used a bare "-", or held a non-numeric bound. Callers should branch on these codes rather than on the length of the returned slice.
When combine is true, Parse merges overlapping and adjacent ranges into the minimal set that covers the same bytes, while preserving the order in which each merged group first appeared. This mirrors the range-parser option of the same name and avoids emitting redundant or touching ranges. ParseRanges is identical to Parse but also returns the requested unit via Ranges.Type, so callers can verify the client actually asked for "bytes". The behavior tracks the npm original closely; the main difference is idiomatic Go typing, with an explicit Range struct and integer result constants in place of JavaScript's array-with-negative-number convention.
Index ¶
Examples ¶
Constants ¶
const ( // ResultOK indicates the header was parsed successfully. ResultOK = 0 // ResultUnsatisfiable indicates none of the ranges overlap the resource. ResultUnsatisfiable = -1 // ResultMalformed indicates the header was malformed or used a bad unit. ResultMalformed = -2 )
Result codes returned alongside the parsed ranges. A negative value indicates an error.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Range ¶
type Range struct {
// Start is the zero-based offset of the first byte in the range.
Start int64
// End is the zero-based offset of the last byte in the range (inclusive).
End int64
}
Range represents a single inclusive byte range [Start, End].
func Parse ¶
Parse parses the given Range header against a resource of the given size.
It returns the slice of resolved inclusive ranges and a result code: 0 on success (ResultOK), -1 (ResultUnsatisfiable) when the ranges cannot be satisfied, and -2 (ResultMalformed) when the header is malformed or uses an unsupported unit. When combine is true, overlapping and adjacent ranges are merged.
Example ¶
ExampleParse resolves a simple byte range against a known resource size. The header "bytes=0-499" asks for the first 500 bytes, which Parse returns as a single inclusive Range from offset 0 to offset 499. The result code is ResultOK (0), signaling that at least one satisfiable range was produced. Both Start and End are inclusive, matching the HTTP specification. Callers branch on the returned code rather than on the slice length.
package main
import (
"fmt"
"github.com/malcolmston/express/rangeparser"
)
func main() {
ranges, code := rangeparser.Parse(1000, "bytes=0-499", false)
fmt.Println(ranges, code)
}
Output: [{0 499}] 0
Example (Combine) ¶
ExampleParse_combine demonstrates the combine option, which merges overlapping and adjacent ranges into the minimal covering set. The first two specs overlap (0-100 and 50-200) and collapse into a single 0-200 range, while 300-400 stays separate because it does not touch the others. Merging preserves the order in which each merged group first appeared. This avoids emitting redundant or touching ranges to the caller. The result code is ResultOK (0).
package main
import (
"fmt"
"github.com/malcolmston/express/rangeparser"
)
func main() {
ranges, code := rangeparser.Parse(1000, "bytes=0-100,50-200,300-400", true)
fmt.Println(ranges, code)
}
Output: [{0 200} {300 400}] 0
Example (Suffix) ¶
ExampleParse_suffix shows a suffix range, where "-500" means the final 500 bytes of the resource rather than an absolute offset. Against a 1000-byte resource this resolves to the inclusive range from offset 500 through 999. Parse translates the suffix form into absolute [Start, End] offsets so callers never have to do the arithmetic. The result code ResultOK (0) confirms the range is satisfiable. Suffix ranges are what let a client request "the last N bytes" without knowing the exact size.
package main
import (
"fmt"
"github.com/malcolmston/express/rangeparser"
)
func main() {
ranges, code := rangeparser.Parse(1000, "bytes=-500", false)
fmt.Println(ranges, code)
}
Output: [{500 999}] 0