0
# Workbox Range Requests
1
2
Workbox Range Requests is a specialized library that provides functionality for handling HTTP range requests in Progressive Web Apps and Service Workers. It enables developers to create partial responses from cached resources when clients request specific byte ranges, which is essential for streaming media content, large file downloads, and bandwidth optimization.
3
4
## Package Information
5
6
- **Package Name**: workbox-range-requests
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install workbox-range-requests`
10
11
## Core Imports
12
13
```typescript
14
import { createPartialResponse, RangeRequestsPlugin } from "workbox-range-requests";
15
```
16
17
For individual imports:
18
19
```typescript
20
import { createPartialResponse } from "workbox-range-requests/createPartialResponse.js";
21
import { RangeRequestsPlugin } from "workbox-range-requests/RangeRequestsPlugin.js";
22
```
23
24
## Basic Usage
25
26
```typescript
27
import { createPartialResponse, RangeRequestsPlugin } from "workbox-range-requests";
28
29
// Using createPartialResponse directly
30
self.addEventListener('fetch', (event) => {
31
if (event.request.headers.has('range')) {
32
event.respondWith(
33
caches.match(event.request).then(async (cachedResponse) => {
34
if (cachedResponse) {
35
return createPartialResponse(event.request, cachedResponse);
36
}
37
return fetch(event.request);
38
})
39
);
40
}
41
});
42
43
// Using RangeRequestsPlugin with Workbox strategies
44
import { registerRoute } from 'workbox-routing';
45
import { CacheFirst } from 'workbox-strategies';
46
47
registerRoute(
48
({ url }) => url.pathname.endsWith('.mp4'),
49
new CacheFirst({
50
cacheName: 'videos',
51
plugins: [new RangeRequestsPlugin()],
52
})
53
);
54
```
55
56
## Architecture
57
58
Workbox Range Requests is built around two key components:
59
60
- **createPartialResponse Function**: Core utility that processes range requests and creates appropriate partial responses with correct HTTP headers
61
- **RangeRequestsPlugin**: Workbox plugin that integrates range request handling seamlessly into caching strategies
62
- **Internal Utilities**: Range header parsing and boundary calculation functions that handle the HTTP Range specification details
63
64
## Capabilities
65
66
### Partial Response Creation
67
68
Creates partial HTTP responses from full cached responses when handling range requests.
69
70
```typescript { .api }
71
/**
72
* Given a Request and Response objects as input, this will return a
73
* promise for a new Response.
74
*
75
* If the original Response already contains partial content (i.e. it has
76
* a status of 206), then this assumes it already fulfills the Range:
77
* requirements, and will return it as-is.
78
*
79
* @param request A request, which should contain a Range header
80
* @param originalResponse A response
81
* @returns Either a 206 Partial Content response with the response body
82
* set to the slice of content specified by the request's Range
83
* header, or a 416 Range Not Satisfiable response if the
84
* conditions of the Range header can't be met
85
*/
86
async function createPartialResponse(
87
request: Request,
88
originalResponse: Response
89
): Promise<Response>;
90
```
91
92
**Usage Examples:**
93
94
```typescript
95
// Handle range request manually
96
const request = new Request('/video.mp4', {
97
headers: { range: 'bytes=1000-2000' }
98
});
99
100
const cachedResponse = await caches.match('/video.mp4');
101
if (cachedResponse) {
102
const partialResponse = await createPartialResponse(request, cachedResponse);
103
// Returns 206 Partial Content response with bytes 1000-2000
104
console.log(partialResponse.status); // 206
105
console.log(partialResponse.headers.get('content-range')); // bytes 1000-2000/totalSize
106
}
107
108
// Error handling - returns 416 for invalid ranges
109
const invalidRequest = new Request('/video.mp4', {
110
headers: { range: 'bytes=9999999-' }
111
});
112
const errorResponse = await createPartialResponse(invalidRequest, cachedResponse);
113
console.log(errorResponse.status); // 416 Range Not Satisfiable
114
```
115
116
### Workbox Integration Plugin
117
118
Plugin that automatically handles range requests within Workbox caching strategies.
119
120
```typescript { .api }
121
/**
122
* The range request plugin makes it easy for a request with a Range header to
123
* be fulfilled by a cached response.
124
*
125
* It does this by intercepting the cachedResponseWillBeUsed plugin callback
126
* and returning the appropriate subset of the cached response body.
127
*/
128
class RangeRequestsPlugin implements WorkboxPlugin {
129
/**
130
* Workbox plugin callback that processes cached responses for range requests
131
* @param param Plugin callback parameters
132
* @param param.request The original request, which may or may not contain a Range header
133
* @param param.cachedResponse The complete cached response
134
* @param param.cacheName The name of the cache
135
* @param param.event The fetch event
136
* @param param.matchOptions Cache query options
137
* @param param.state Plugin state object
138
* @returns If request contains a Range header, then a new response with status 206
139
* whose body is a subset of cachedResponse is returned. Otherwise,
140
* cachedResponse is returned as-is
141
*/
142
cachedResponseWillBeUsed(param: {
143
cacheName: string;
144
request: Request;
145
cachedResponse?: Response;
146
event: ExtendableEvent;
147
matchOptions?: CacheQueryOptions;
148
state?: PluginState;
149
}): Promise<Response | void | null | undefined>;
150
}
151
152
// WorkboxPlugin interface from workbox-core
153
interface WorkboxPlugin {
154
cachedResponseWillBeUsed?: (param: {
155
cacheName: string;
156
request: Request;
157
cachedResponse?: Response;
158
event: ExtendableEvent;
159
matchOptions?: CacheQueryOptions;
160
state?: PluginState;
161
}) => Promise<Response | void | null | undefined>;
162
}
163
164
// Additional types from workbox-core
165
interface PluginState {
166
[key: string]: any;
167
}
168
```
169
170
**Usage Examples:**
171
172
```typescript
173
import { registerRoute } from 'workbox-routing';
174
import { CacheFirst } from 'workbox-strategies';
175
import { RangeRequestsPlugin } from 'workbox-range-requests';
176
177
// Use with any Workbox strategy for media files
178
registerRoute(
179
({ url }) => url.pathname.match(/\.(mp4|webm|mp3)$/),
180
new CacheFirst({
181
cacheName: 'media-cache',
182
plugins: [new RangeRequestsPlugin()],
183
})
184
);
185
186
// Works with other strategies too
187
import { StaleWhileRevalidate } from 'workbox-strategies';
188
189
registerRoute(
190
({ url }) => url.pathname.includes('/large-files/'),
191
new StaleWhileRevalidate({
192
cacheName: 'large-files',
193
plugins: [new RangeRequestsPlugin()],
194
})
195
);
196
```
197
198
## Error Handling
199
200
The library provides graceful error handling for various edge cases:
201
202
- **Missing Range Header**: Returns original response as-is
203
- **Invalid Range Format**: Returns 416 Range Not Satisfiable
204
- **Out of Bounds Range**: Returns 416 Range Not Satisfiable
205
- **Already Partial Response**: Returns existing 206 response unchanged
206
- **Null/Undefined Responses**: Returns appropriate error responses
207
208
```typescript
209
// The library handles these scenarios automatically:
210
211
// No range header - returns original response
212
const noRangeRequest = new Request('/file.pdf');
213
const response1 = await createPartialResponse(noRangeRequest, cachedResponse);
214
// Returns original cachedResponse unchanged
215
216
// Invalid range - returns 416 error
217
const invalidRequest = new Request('/file.pdf', {
218
headers: { range: 'invalid-range-header' }
219
});
220
const response2 = await createPartialResponse(invalidRequest, cachedResponse);
221
// Returns 416 Range Not Satisfiable
222
223
// Already partial content - passes through
224
const partialResponse = new Response(blob, { status: 206 });
225
const response3 = await createPartialResponse(rangeRequest, partialResponse);
226
// Returns the existing 206 response as-is
227
```