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`
- Default: `true`
As most of our cache strategies depends on well known defined HTTP headers, most browsers
also use those headers to define their own cache strategies and storages.
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.
::: 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
with we and your browser caching the response, resulting in a **double layer of cache**.
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**.
This option solves this by including some predefined headers in the request, that should
tell any client / adapter to not cache the response, thus only we will cache it.
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.
**These are headers used in our specific request, it won't affect any other request or
response that the server may handle.**
**These headers are added to your specific request and won't affect any other request or response that the server may handle.**
Headers included:
- `Cache-Control: no-cache`
- `Cache-Control: no-cache, no-store, must-revalidate`
- `Pragma: no-cache`
- `Expires: 0`
::: warning
::: tip Alternative
This option will not work on most **CORS** requests, as the browser will throw
`Request header field pragma is not allowed by Access-Control-Allow-Headers in preflight response.`.
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.
When you encounter CORS error, you need to make sure `Cache-Control`, `Pragma` and
`Expires` headers are included into your server's `Access-Control-Allow-Headers` CORS
configuration.
For maximum reliability, add a unique random query parameter instead:
If you cannot do such thing, you can fallback to disabling this option. Learn more on why
it should be enabled at
[#437](https://github.com/arthurfiorette/axios-cache-interceptor/issues/437#issuecomment-1361262194)
and in this [StackOverflow](https://stackoverflow.com/a/62781874/14681561) answer.
```ts
axios.get(
`/api/data?cachebuster=${Math.random().toString(36).slice(2)}`,
{
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
// shouldn't be cached an therefore neither in the browser.
// https://stackoverflow.com/a/2068407
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.Expires] ??= '0';
}

View File

@ -366,7 +366,7 @@ describe('Request Interceptor', () => {
const req1 = await axios.get('url');
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, */*',
'Content-Type': undefined,
[Header.Pragma]: 'no-cache',