or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

caching.mdconfiguration.mdcore-fetch.mdindex.mdnetwork.mdretry.mdsecurity.md

caching.mddocs/

0

# HTTP Caching

1

2

Advanced HTTP caching system that follows RFC 7234 specifications with cache control, ETags, conditional requests, and intelligent cache validation.

3

4

## Capabilities

5

6

### Cache Configuration

7

8

Configure HTTP caching behavior through options that control cache storage, retrieval, and validation policies.

9

10

```javascript { .api }

11

/**

12

* Cache configuration options

13

*/

14

interface CacheOptions {

15

cachePath?: string; // Path to cache directory (required for caching)

16

cache?: CacheMode; // Cache mode controlling behavior

17

cacheAdditionalHeaders?: string[]; // Additional headers to store in cache

18

}

19

20

/**

21

* Cache modes following fetch specification

22

*/

23

type CacheMode =

24

| 'default' // Standard caching with revalidation

25

| 'no-store' // No caching

26

| 'reload' // Bypass cache, update with response

27

| 'no-cache' // Always revalidate

28

| 'force-cache' // Use cache regardless of staleness

29

| 'only-if-cached'; // Only use cached responses, error if none

30

```

31

32

**Usage Examples:**

33

34

```javascript

35

const fetch = require('make-fetch-happen');

36

37

// Enable caching with default behavior

38

const response = await fetch('https://api.example.com/data', {

39

cachePath: './my-cache'

40

});

41

42

// Different cache modes

43

const cachedFetch = fetch.defaults({ cachePath: './cache' });

44

45

// Use cache regardless of staleness

46

const staleResponse = await cachedFetch('https://api.example.com/config', {

47

cache: 'force-cache'

48

});

49

50

// Always revalidate before using cache

51

const freshResponse = await cachedFetch('https://api.example.com/users', {

52

cache: 'no-cache'

53

});

54

55

// Only use cache, fail if not cached

56

try {

57

const offlineResponse = await cachedFetch('https://api.example.com/offline-data', {

58

cache: 'only-if-cached'

59

});

60

} catch (error) {

61

console.log('Not cached:', error.code); // ENOTCACHED

62

}

63

```

64

65

### Cache Modes

66

67

Detailed behavior of each cache mode:

68

69

```javascript { .api }

70

/**

71

* Cache mode behaviors:

72

*

73

* 'default': Check cache for fresh response, use it. If stale, make conditional

74

* request for revalidation. If network fails, use stale cache.

75

*

76

* 'no-store': Never use cache, never store responses in cache.

77

*

78

* 'reload': Always make network request, store response in cache.

79

*

80

* 'no-cache': Always make conditional request if cached response exists,

81

* otherwise make normal request. Store response in cache.

82

*

83

* 'force-cache': Use any cached response regardless of staleness. If no

84

* cached response, make normal request and store in cache.

85

*

86

* 'only-if-cached': Use cached response regardless of staleness. If no

87

* cached response, throw ENOTCACHED error.

88

*/

89

```

90

91

### Additional Cache Headers

92

93

Store custom headers in the cache beyond the standard set:

94

95

```javascript { .api }

96

/**

97

* Default headers stored in cache:

98

* cache-control, content-encoding, content-language, content-type,

99

* date, etag, expires, last-modified, link, location, pragma, vary

100

*

101

* Add custom headers with cacheAdditionalHeaders option

102

*/

103

```

104

105

**Usage Examples:**

106

107

```javascript

108

// Store custom headers in cache

109

const response = await fetch('https://api.example.com/data', {

110

cachePath: './cache',

111

cacheAdditionalHeaders: [

112

'x-rate-limit-remaining',

113

'x-api-version',

114

'x-request-id'

115

]

116

});

117

118

// Custom headers will be available on cached responses

119

const cachedResponse = await fetch('https://api.example.com/data', {

120

cachePath: './cache',

121

cache: 'force-cache'

122

});

123

124

console.log(cachedResponse.headers.get('x-rate-limit-remaining'));

125

```

126

127

### Cache Response Headers

128

129

make-fetch-happen adds metadata headers to cached responses:

130

131

```javascript { .api }

132

/**

133

* Special headers added to cached responses:

134

*/

135

interface CacheResponseHeaders {

136

'x-local-cache': string; // Path to cache directory

137

'x-local-cache-key': string; // Unique cache key for this response

138

'x-local-cache-mode': 'stream'; // Always 'stream'

139

'x-local-cache-hash': string; // Integrity hash of cached content

140

'x-local-cache-status': CacheStatus; // How response was generated

141

'x-local-cache-time': string; // ISO timestamp of cache insertion

142

}

143

144

type CacheStatus =

145

| 'miss' // Not in cache, fetched from network

146

| 'hit' // Fresh cache hit

147

| 'stale' // Stale cache hit (returned without revalidation)

148

| 'revalidated' // Stale cache revalidated (304 response)

149

| 'updated' // Stale cache updated with new response

150

| 'skip'; // Cache bypassed

151

```

152

153

**Usage Examples:**

154

155

```javascript

156

const response = await fetch('https://api.example.com/data', {

157

cachePath: './cache'

158

});

159

160

// Check cache status

161

const cacheStatus = response.headers.get('x-local-cache-status');

162

console.log('Cache status:', cacheStatus); // 'miss', 'hit', etc.

163

164

// Get cache timing information

165

const cacheTime = response.headers.get('x-local-cache-time');

166

if (cacheTime) {

167

console.log('Cached at:', new Date(cacheTime));

168

}

169

```

170

171

### Manual Cache Access

172

173

Access cached entries directly using cacache:

174

175

```javascript { .api }

176

/**

177

* Manual cache access (requires cacache dependency)

178

*/

179

const cacache = require('cacache');

180

181

// Get cached entry using response headers

182

const getCachedEntry = async (response) => {

183

const cachePath = response.headers.get('x-local-cache');

184

const cacheKey = response.headers.get('x-local-cache-key');

185

186

if (cachePath && cacheKey) {

187

return await cacache.get(cachePath, cacheKey);

188

}

189

};

190

191

// Get content by integrity hash

192

const getCachedContent = async (response) => {

193

const cachePath = response.headers.get('x-local-cache');

194

const cacheHash = response.headers.get('x-local-cache-hash');

195

196

if (cachePath && cacheHash) {

197

return await cacache.get.byDigest(cachePath, cacheHash);

198

}

199

};

200

```

201

202

### Cache Invalidation

203

204

Caches are automatically invalidated for successful non-GET/HEAD requests:

205

206

```javascript { .api }

207

/**

208

* Automatic cache invalidation occurs when:

209

* - Request method is not GET or HEAD

210

* - Response status is 200-399

211

* - Request has a cachePath configured

212

*

213

* This ensures cached data remains consistent after mutations

214

*/

215

```

216

217

**Usage Examples:**

218

219

```javascript

220

const apiFetch = fetch.defaults({ cachePath: './cache' });

221

222

// GET request - uses and populates cache

223

const userData = await apiFetch('https://api.example.com/users/123');

224

225

// POST request - invalidates cache for this URL

226

await apiFetch('https://api.example.com/users/123', {

227

method: 'POST',

228

body: JSON.stringify({ name: 'Updated Name' }),

229

headers: { 'Content-Type': 'application/json' }

230

});

231

232

// Next GET will fetch fresh data

233

const updatedData = await apiFetch('https://api.example.com/users/123');

234

```

235

236

### Cache Storage Requirements

237

238

Caching behavior depends on proper cache directory setup:

239

240

```javascript { .api }

241

/**

242

* Cache requirements:

243

* - cachePath must be specified to enable caching

244

* - Directory must be writable by the process

245

* - Only GET and HEAD requests are cached

246

* - Responses must be consumed (json(), text(), buffer(), etc.) to be cached

247

*/

248

```

249

250

**Usage Examples:**

251

252

```javascript

253

// Ensure response is consumed for caching

254

const response = await fetch('https://api.example.com/data', {

255

cachePath: './cache'

256

});

257

258

// Must consume response body for caching to work

259

const data = await response.json(); // or .text(), .buffer(), etc.

260

261

// Stream responses are also cached

262

const streamResponse = await fetch('https://api.example.com/large-file', {

263

cachePath: './cache'

264

});

265

266

// Pipe to destination (response will be cached)

267

streamResponse.body.pipe(fs.createWriteStream('./downloaded-file'));

268

```