Update Cache-Control header to prevent caching (#1091)

This commit is contained in:
Arthur Fiorette 2025-09-15 12:36:51 -03:00 committed by GitHub
parent 3236cd3a10
commit 2c8910b848
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 374 additions and 21 deletions

1
.serena/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/cache

View File

@ -0,0 +1,50 @@
# Code Style and Conventions
## Language and Configuration
- **TypeScript**: Strict mode enabled with comprehensive type checking
- **Module System**: ESNext with NodeNext module resolution
- **Target**: ESNext for modern JavaScript features
## Code Quality Tools
- **Biome**: Used for linting, formatting, and code quality
- Configuration extends `@arthurfiorette/biomejs-config`
- Excludes build directories, dist, dev, coverage, node_modules
- **TypeScript**: Strict configuration with all strict flags enabled
## TypeScript Configuration Highlights
- `strict: true` - All strict type checking enabled
- `noImplicitAny: true`
- `strictNullChecks: true`
- `noUnusedLocals: true`
- `noUnusedParameters: true`
- `noImplicitReturns: true`
- `noUncheckedIndexedAccess: true`
- `verbatimModuleSyntax: true`
## File Structure Conventions
- Use `.ts` extensions for TypeScript files
- Use `.js` extensions in import statements (for ESM compatibility)
- Mirror test file structure with source files
- Use kebab-case for file names when multiple words
## Import/Export Conventions
- Use named exports primarily
- Main `index.ts` re-exports all public APIs
- Use `.js` extensions in imports (transpiled to correct format)
## Development Build Support
- Uses `__ACI_DEV__` global constant for development-specific code
- Development builds include console warnings
- Production builds strip development code
## Code Organization
- Modular architecture with clear separation of concerns
- Each module has its own directory with related types
- Utilities are separated into dedicated util modules

View File

@ -0,0 +1,49 @@
# Codebase Structure
## Root Directory
- `src/` - Main source code
- `test/` - Test files (mirrors src structure)
- `docs/` - VitePress documentation
- `examples/` - Usage examples
- `benchmark/` - Performance benchmarks
- `build.sh` - Custom build script
- `package.json` - Project configuration
- `biome.json` - Code quality configuration
- `tsconfig.json` - TypeScript configuration
## Source Code Structure (`src/`)
### Core Modules
- `index.ts` - Main entry point (exports all modules)
- `cache/` - Core caching functionality
- `axios.ts` - Axios integration
- `cache.ts` - Cache implementation
- `create.ts` - Cache creation utilities
- `interceptors/` - Request/response interceptors
- `request.ts` - Request interceptor logic
- `response.ts` - Response interceptor logic
- `build.ts` - Interceptor building utilities
- `util.ts` - Interceptor utilities
- `storage/` - Storage adapters
- `memory.ts` - In-memory storage
- `web-api.ts` - Web API storage (localStorage, etc.)
- `build.ts` - Storage building utilities
- `types.ts` - Storage type definitions
- `header/` - HTTP header handling
- `headers.ts` - Header utilities
- `interpreter.ts` - Cache header interpretation
- `types.ts` - Header type definitions
- `util/` - General utilities
- `cache-predicate.ts` - Cache condition checking
- `key-generator.ts` - Cache key generation
- `update-cache.ts` - Cache updating logic
- `types.ts` - Utility type definitions
## Test Structure (`test/`)
- Mirrors the `src/` directory structure
- Uses Node.js built-in test runner
- Includes mock utilities in `test/mocks/`
- Setup file: `test/setup.js`

View File

@ -0,0 +1,42 @@
# Axios Cache Interceptor - Project Overview
## Purpose
Axios Cache Interceptor is a cache interceptor for axios designed with developers and performance in mind. It allows developers to call axios multiple times without worrying about overloading the network or implementing a simple and buggy cache system themselves.
## Key Features
- ⚡ Performance optimized
- 📦 Multiple build targets (ESM, CJS, UMD)
- 🔩 Easy to use - just wrap your axios instance
- 🛠️ Rich caching features (ETags, Last-Modified, Cache-Control, etc.)
- 🌐 Reduces network waste through intelligent caching
- 🔑 Full TypeScript support
## Tech Stack
- **Language**: TypeScript
- **Package Manager**: pnpm (v9.1.1)
- **Node Version**: >=12 (configured in .nvmrc)
- **Build Tool**: microbundle (for multiple output formats)
- **Code Quality**: Biome (linting, formatting, type checking)
- **Testing**: Node.js built-in test runner with c8 for coverage
- **Documentation**: VitePress
## Basic Usage
```ts
import Axios from 'axios';
import { setupCache } from 'axios-cache-interceptor';
const instance = Axios.create();
const axios = setupCache(instance);
const req1 = axios.get('https://arthur.place/');
const req2 = axios.get('https://arthur.place/');
const [res1, res2] = await Promise.all([req1, req2]);
res1.cached; // false
res2.cached; // true
```

View File

@ -0,0 +1,48 @@
# Suggested Commands
## Development Commands
### Code Quality
- `pnpm lint` - Check code quality with Biome
- `pnpm lint-fix` - Fix code quality issues with Biome (including unsafe fixes)
- `pnpm lint-ci` - Run linting for CI (strict mode)
- `pnpm format` - Format code with Biome
### Testing
- `pnpm test` - Run all tests with coverage (using Node.js test runner + c8)
- `pnpm test:only` - Run only tests marked with `test.only`
- `pnpm test:types` - Run TypeScript type checking
### Building
- `pnpm build` - Build the project (runs build.sh script)
- `bash build.sh` - Direct build script execution
### Documentation
- `pnpm docs:dev` - Start development documentation server (port 1227)
- `pnpm docs:build` - Build documentation
- `pnpm docs:serve` - Serve built documentation
### Other
- `pnpm benchmark` - Run performance benchmarks
- `pnpm version` - Update version and changelog
## Build Outputs
- `dist/` - Production builds (multiple formats: ESM, CJS, Modern, UMD)
- `dev/` - Development builds with debug information
- Both include TypeScript declaration files
## Package Manager
- Uses **pnpm** as the package manager
- Version: 9.1.1 (specified in packageManager field)
## Node Version
- Minimum: Node.js >=12
- Uses `.nvmrc` for version specification

View File

@ -0,0 +1,37 @@
# System Utilities and Environment
## System Information
- **Platform**: Linux
- **OS**: Linux 5.15.133.1-microsoft-standard-WSL2 (WSL2 environment)
- **Shell**: Bash
## Available System Commands
- `git` - Git version control
- `ls` - List directory contents
- `cd` - Change directory
- `find` - Find files and directories
- `grep` - Search text patterns
- `bash` - Execute bash scripts
- `node` - Node.js runtime
- `pnpm` - Package manager
## Git Information
- **Current Branch**: arthurfiorette/safari-takeover
- **Main Branch**: main (use for PRs)
- **Status**: Clean working directory
## Project Environment
- **Working Directory**: /home/hzk/dev/axios-cache-interceptor
- **Git Repository**: Yes
- **Package Manager**: pnpm (version 9.1.1)
- **Node Version**: >=12 (specified in package.json engines)
## Special Considerations for Linux/WSL2
- File permissions may need attention
- Cross-platform compatibility is maintained in build scripts
- Uses Unix-style line endings (`newLine: "lf"` in tsconfig)

View File

@ -0,0 +1,43 @@
# Task Completion Workflow
## Commands to Run After Completing Tasks
### Code Quality Checks (Required)
1. `pnpm lint` - Check for linting issues
2. `pnpm lint-fix` - Auto-fix linting issues (if needed)
3. `pnpm test:types` - Verify TypeScript type checking passes
### Testing (Required)
4. `pnpm test` - Run all tests with coverage to ensure nothing is broken
### Build Verification (When Applicable)
5. `pnpm build` - Verify the build process works correctly (when changes affect build)
### Documentation (When Applicable)
6. `pnpm docs:build` - Verify documentation builds correctly (when docs are modified)
## Workflow Order
1. **First**: Fix any linting issues with `pnpm lint-fix`
2. **Second**: Ensure types are correct with `pnpm test:types`
3. **Third**: Run tests to verify functionality with `pnpm test`
4. **Fourth**: Build if necessary with `pnpm build`
5. **Finally**: Check documentation builds if docs were modified
## Pre-commit Considerations
- The project uses strict TypeScript configuration
- All tests must pass
- Code must pass linting
- Type checking must pass
- Build must succeed for production releases
## Development vs Production
- Development builds include debug information via `__ACI_DEV__` flag
- Production builds strip debug code for optimal performance
- Both are built simultaneously by the build script

67
.serena/project.yml Normal file
View File

@ -0,0 +1,67 @@
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
# * For C, use cpp
# * For JavaScript, use typescript
# Special requirements:
# * csharp: Requires the presence of a .sln file in the project folder.
language: typescript
# whether to use the project's gitignore file to ignore files
# Added on 2025-04-07
ignore_all_files_in_gitignore: true
# list of additional paths to ignore
# same syntax as gitignore, so you can use * and **
# Was previously called `ignored_dirs`, please update your config if you are using that.
# Added (renamed) on 2025-04-07
ignored_paths: []
# whether the project is in read-only mode
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
# Added on 2025-04-18
read_only: false
# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
# Below is the complete list of tools for convenience.
# To make sure you have the latest list of tools, and to view their descriptions,
# execute `uv run scripts/print_tool_overview.py`.
#
# * `activate_project`: Activates a project by name.
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
# * `create_text_file`: Creates/overwrites a file in the project directory.
# * `delete_lines`: Deletes a range of lines within a file.
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
# * `execute_shell_command`: Executes a shell command.
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
# * `initial_instructions`: Gets the initial instructions for the current project.
# Should only be used in settings where the system prompt cannot be set,
# e.g. in clients you have no control over, like Claude Desktop.
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
# * `insert_at_line`: Inserts content at a given line in a file.
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
# * `list_memories`: Lists memories in Serena's project-specific memory store.
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
# * `read_file`: Reads a file within the project directory.
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
# * `remove_project`: Removes a project from the Serena configuration.
# * `replace_lines`: Replaces a range of lines within a file with new content.
# * `replace_symbol_body`: Replaces the full definition of a symbol.
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
# * `search_for_pattern`: Performs a search for a pattern in the project.
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
# * `switch_modes`: Activates modes by providing a list of their names
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
excluded_tools: []
# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ''
project_name: 'axios-cache-interceptor'

View File

@ -103,8 +103,7 @@ method for more information.
- Type: `boolean` - Type: `boolean`
- Default: `true` - Default: `true`
As most of our cache strategies depends on well known defined HTTP headers, most browsers As most of our cache strategies depend on well-known HTTP headers, most browsers also use those headers to define their own cache strategies and storages.
also use those headers to define their own cache strategies and storages.
::: details This can be seen when opening network tab in your browser's dev tools. ::: details This can be seen when opening network tab in your browser's dev tools.
@ -112,34 +111,50 @@ also use those headers to define their own cache strategies and storages.
::: :::
When your requested routes includes `Cache-Control` in their responses, you may end up When your requested routes include `Cache-Control` in their responses, you may end up with both the library and your browser caching the response, resulting in a **double layer of cache**.
with we and your browser caching the response, resulting in a **double layer of cache**.
This option solves this by including some predefined headers in the request, that should This option solves this by including predefined headers in the request that instruct any client/adapter to not cache the response, thus ensuring only the library caches it.
tell any client / adapter to not cache the response, thus only we will cache it.
**These are headers used in our specific request, it won't affect any other request or **These headers are added to your specific request and won't affect any other request or response that the server may handle.**
response that the server may handle.**
Headers included: Headers included:
- `Cache-Control: no-cache` - `Cache-Control: no-cache, no-store, must-revalidate`
- `Pragma: no-cache` - `Pragma: no-cache`
- `Expires: 0` - `Expires: 0`
::: warning ::: tip Alternative
This option will not work on most **CORS** requests, as the browser will throw While `cacheTakeover` works for most browsers according to [this StackOverflow answer](https://stackoverflow.com/a/2068407), in some rare edge cases it may be unreliable due to browser-specific cache behaviors or network intermediaries.
`Request header field pragma is not allowed by Access-Control-Allow-Headers in preflight response.`.
When you encounter CORS error, you need to make sure `Cache-Control`, `Pragma` and For maximum reliability, add a unique random query parameter instead:
`Expires` headers are included into your server's `Access-Control-Allow-Headers` CORS
configuration.
If you cannot do such thing, you can fallback to disabling this option. Learn more on why ```ts
it should be enabled at axios.get(
[#437](https://github.com/arthurfiorette/axios-cache-interceptor/issues/437#issuecomment-1361262194) `/api/data?cachebuster=${Math.random().toString(36).slice(2)}`,
and in this [StackOverflow](https://stackoverflow.com/a/62781874/14681561) answer. {
id: 'api-data-endpoint' // Keep same cache key despite different URLs
}
);
```
Your backend can ignore the `cachebuster` value. This **guarantees** no browser caching while preserving axios-cache-interceptor functionality.
:::
::: warning CORS Considerations
This option will not work on **CORS** requests with restricted headers, as the browser will throw:
`Request header field Pragma is not allowed by Access-Control-Allow-Headers in preflight response.`
When you encounter CORS errors, you need to ensure `Cache-Control`, `Pragma`, and `Expires` headers are included in your server's `Access-Control-Allow-Headers` CORS configuration.
If you cannot modify the CORS configuration, you can:
1. Disable this option (`cacheTakeover: false`)
2. Use the query parameter approach mentioned above
Learn more about why this should be enabled at [#437](https://github.com/arthurfiorette/axios-cache-interceptor/issues/437#issuecomment-1361262194) and in this [StackOverflow answer](https://stackoverflow.com/a/2068407).
::: :::

View File

@ -99,8 +99,9 @@ export function defaultRequestInterceptor(axios: AxiosCacheInstance): RequestInt
// //
// Its currently used before isMethodIn because if the isMethodIn returns false, the request // Its currently used before isMethodIn because if the isMethodIn returns false, the request
// shouldn't be cached an therefore neither in the browser. // shouldn't be cached an therefore neither in the browser.
// https://stackoverflow.com/a/2068407
if (config.cache.cacheTakeover) { if (config.cache.cacheTakeover) {
config.headers[Header.CacheControl] ??= 'no-cache'; config.headers[Header.CacheControl] ??= 'no-cache, no-store, must-revalidate';
config.headers[Header.Pragma] ??= 'no-cache'; config.headers[Header.Pragma] ??= 'no-cache';
config.headers[Header.Expires] ??= '0'; config.headers[Header.Expires] ??= '0';
} }

View File

@ -366,7 +366,7 @@ describe('Request Interceptor', () => {
const req1 = await axios.get('url'); const req1 = await axios.get('url');
assert.deepEqual(Object.assign({}, req1.request.config.headers), { assert.deepEqual(Object.assign({}, req1.request.config.headers), {
[Header.CacheControl]: 'no-cache', [Header.CacheControl]: 'no-cache, no-store, must-revalidate',
Accept: 'application/json, text/plain, */*', Accept: 'application/json, text/plain, */*',
'Content-Type': undefined, 'Content-Type': undefined,
[Header.Pragma]: 'no-cache', [Header.Pragma]: 'no-cache',