or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

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

```