Skip to content

Latest commit

 

History

History
1069 lines (882 loc) · 31.4 KB

File metadata and controls

1069 lines (882 loc) · 31.4 KB

Testing Guide

CLI Argument Parsing Tests

✅ Test 1: Help Command

node src/index.js --help

Expected: Display help information with all available options

✅ Test 2: Valid Server Start

node src/index.js --port 3000 --origin http://dummyjson.com

Expected: Show server starting with validated port and origin

✅ Test 3: Clear Cache Command

node src/index.js --clear-cache

Expected: Show cache clearing message

✅ Test 4: Invalid Port (Out of Range)

node src/index.js --port 99999 --origin http://dummyjson.com

Expected: Error message "Port must be between 1 and 65535"

✅ Test 5: Invalid URL Format

node src/index.js --port 3000 --origin invalid-url

Expected: Error message "Invalid origin URL"

✅ Test 6: Missing Arguments

node src/index.js

Expected: Usage examples and error message

✅ Test 7: Version Command

node src/index.js --version

Expected: Display version number (1.0.0)

Test Results Summary

Test Case Status Notes
Help display ✅ PASS Shows all options
Valid arguments ✅ PASS Validates and accepts
Clear cache flag ✅ PASS Recognized correctly
Invalid port ✅ PASS Proper validation
Invalid URL ✅ PASS Proper validation
No arguments ✅ PASS Shows usage guide
Version flag ✅ PASS Shows version

Stage 3 Tests - HTTP Server

✅ Test 8: Server Starts and Listens

node src/index.js --port 3000 --origin http://dummyjson.com

Expected: Server starts and listens on port 3000 Result: ✅ PASS - Server running successfully

✅ Test 9: Server Responds to Requests

curl http://localhost:3000/test

Expected: Server responds with acknowledgment message Result: ✅ PASS - Returns "Proxy server received: GET /test"

✅ Test 10: Server Handles Different Endpoints

curl http://localhost:3000/products

Expected: Server responds to any endpoint Result: ✅ PASS - Responds correctly

✅ Test 11: Request Forwarding to Origin

node src/index.js --port 3002 --origin https://dummyjson.com
curl http://localhost:3002/products/1

Expected: Proxy forwards request to origin and returns actual data Result: ✅ PASS - Returns JSON data from dummyjson.com

✅ Test 12: Query Parameters Forwarding

curl http://localhost:3002/products?limit=3

Expected: Query parameters are forwarded correctly Result: ✅ PASS - Returns limited results with all headers preserved

✅ Test 13: HTTP to HTTPS Forwarding

node src/index.js --port 3002 --origin https://dummyjson.com

Expected: Proxy handles HTTPS origin servers Result: ✅ PASS - Successfully forwards to HTTPS origins

✅ Test 14: Status Code Forwarding

curl -i http://localhost:3002/products/1

Expected: Status codes from origin are forwarded to client Result: ✅ PASS - HTTP 200 status code properly forwarded

✅ Test 15: POST Method with JSON Body

curl -X POST -H "Content-Type: application/json" \
  -d '{"title":"Test Product","price":99.99}' \
  http://localhost:3000/products/add

Expected: POST request with body is forwarded correctly Result: ✅ PASS - Returns {"id":195,"title":"Test Product","price":99.99} Server Log: 📤 POST /products/add📥 201 POST /products/add

✅ Test 16: PUT Method with JSON Body

curl -X PUT -H "Content-Type: application/json" \
  -d '{"title":"Updated Product"}' \
  http://localhost:3000/products/1

Expected: PUT request updates resource Result: ✅ PASS - Returns updated product data Server Log: 📤 PUT /products/1📥 200 PUT /products/1

✅ Test 17: DELETE Method

curl -X DELETE http://localhost:3000/products/1

Expected: DELETE request is forwarded Result: ✅ PASS - Returns deleted product with "isDeleted":true Server Log: 📤 DELETE /products/1📥 200 DELETE /products/1

✅ Test 18: PATCH Method

curl -X PATCH -H "Content-Type: application/json" \
  -d '{"price":199.99}' \
  http://localhost:3000/products/1

Expected: PATCH request partially updates resource Result: ✅ PASS - Returns product with updated price Server Log: 📤 PATCH /products/1📥 200 PATCH /products/1

HTTP Methods Summary

All HTTP methods are supported:

  • ✅ GET (read)
  • ✅ POST (create)
  • ✅ PUT (update/replace)
  • ✅ PATCH (partial update)
  • ✅ DELETE (delete)
  • ✅ HEAD, OPTIONS, etc. (all methods forwarded)

✅ Test 19: Query Parameters Preservation

curl "http://localhost:3000/products?limit=2&skip=10"

Expected: Query parameters forwarded to origin Result: ✅ PASS - Response shows "skip":10,"limit":2 confirming params preserved

✅ Test 20: Request Headers Preservation

curl -X POST -H "Content-Type: application/json" \
  -H "User-Agent: MyTestAgent/1.0" \
  -H "X-Custom-Header: MyCustomValue" \
  -d '{"title":"Header Test","price":123.45}' \
  http://localhost:3000/products/add

Expected: All custom headers forwarded to origin Result: ✅ PASS - Request successful with all headers

✅ Test 21: Request Body Preservation

curl -X POST -H "Content-Type: application/json" \
  -d '{"title":"Body Test","price":99.99,"description":"Testing"}' \
  http://localhost:3000/products/add

Expected: Complete request body forwarded Result: ✅ PASS - Response includes all fields from request body

✅ Test 22: Combined Preservation Test

curl -X PUT -H "Authorization: Bearer token" \
  -d '{"title":"Updated","price":199.99}' \
  "http://localhost:3000/products/1?validate=true"

Expected: Query params, headers, and body all preserved Result: ✅ PASS - All elements forwarded correctly

Preservation Features Summary

Query Parameters: Preserved using targetUrl.searchRequest Headers: Preserved using spread operator ...req.headersRequest Body: Preserved using streaming req.pipe(proxyReq)HTTP Method: Preserved using req.methodContent-Type: Preserved in headers ✅ Authorization: Preserved in headers ✅ Custom Headers: All custom headers preserved

✅ Test 23: Response Headers Forwarding

curl -i http://localhost:3000/products/1

Expected: All response headers from origin are forwarded to client Result: ✅ PASS - 23 headers forwarded including:

  • Content-Type, Server, Date, Connection
  • Cache-Control, ETag, Vary
  • Security headers (X-Frame-Options, Strict-Transport-Security, X-XSS-Protection)
  • CORS headers (Access-Control-Allow-Origin)
  • Rate limiting headers (X-RateLimit-Limit, X-RateLimit-Remaining)
  • Cloudflare headers (CF-Cache-Status, CF-Ray)
  • Custom headers (Report-To, NEL)

✅ Test 24: Status Code Forwarding

curl -i http://localhost:3000/products/999999

Expected: HTTP status codes are forwarded (404, 500, etc.) Result: ✅ PASS - Status codes properly forwarded

Response Forwarding Summary

All Headers Forwarded: 23+ headers including standard, security, CORS, and custom ✅ Status Codes: All HTTP status codes (200, 201, 404, 500, etc.) ✅ Response Body: Complete body streamed using pipe ✅ Content-Type: Preserved (JSON, HTML, XML, binary, etc.) ✅ Encoding: Transfer-Encoding and Content-Encoding preserved

Stage 3 Complete ✅

All proxy forwarding functionality is working:

  • ✅ HTTP server listening on custom port
  • ✅ Request forwarding to origin (HTTP/HTTPS)
  • ✅ All HTTP methods supported
  • ✅ Request preservation (headers, query params, body)
  • ✅ Response forwarding (status, headers, body)

Stage 4 Tests - Caching Mechanism

✅ Test 25: Cache Key Generation - Basic URL

node test-cache-keys.js

Input: GET https://dummyjson.com/products/1 Key: GET:https://dummyjson.com/products/1 Result: ✅ PASS - Simple, readable format

✅ Test 26: Cache Key with Query Parameters

Input: GET https://dummyjson.com/products?limit=10&skip=5 Key: GET:https://dummyjson.com/products?limit=10&skip=5 Result: ✅ PASS - Query params automatically included

✅ Test 27: Different Query Params = Different Keys

Keys:

  • GET:https://dummyjson.com/products?limit=10
  • GET:https://dummyjson.com/products?limit=20 Result: ✅ PASS - Keys are different (correct behavior)

✅ Test 28: Different HTTP Methods = Different Keys

Same URL, different methods:

  • GET:https://dummyjson.com/products/1
  • POST:https://dummyjson.com/products/1
  • PUT:https://dummyjson.com/products/1 Result: ✅ PASS - All keys are unique

✅ Test 29: Method Case Normalization

Input: get, GET, Get All normalize to: GET:https://dummyjson.com/products/1 Result: ✅ PASS - Case-insensitive method handling

Cache Key Strategy Summary

Format: METHOD:URL

Benefits:

  • ✅ Simple and human-readable
  • ✅ Unique for each request combination
  • ✅ Automatically includes query parameters
  • ✅ Method-aware (GET vs POST cached separately)
  • ✅ Case-insensitive method handling
  • ✅ Efficient for Map lookups

Examples:

GET:https://dummyjson.com/products/1
GET:https://dummyjson.com/products?limit=10&skip=5
POST:https://dummyjson.com/products/add
PUT:https://dummyjson.com/products/1
DELETE:https://dummyjson.com/products/1

✅ Test 30: Initial Cache State

node test-cache-storage.js

Expected: Empty cache (size = 0) Result: ✅ PASS - Cache starts empty

✅ Test 31: Store Response in Cache

Action: Store a mock response with status, headers, body Expected: Cache size = 1 Result: ✅ PASS - Response successfully stored

✅ Test 32: Retrieve Cached Response

Action: Retrieve previously stored response Expected: Returns complete response object Result: ✅ PASS - Retrieved with statusCode, headers, body

✅ Test 33: Cache Miss

Action: Request non-existent cache entry Expected: Returns null Result: ✅ PASS - Properly handles cache misses

✅ Test 34: Store Multiple Responses

Action: Store 3 different responses Expected: Cache size = 3, all retrievable Result: ✅ PASS - All entries stored and retrievable

✅ Test 35: Method Differentiation

Action: Store GET and POST to same URL Expected: Cached separately (2 entries) Result: ✅ PASS - GET and POST cached independently

✅ Test 36: Overwrite Existing Entry

Action: Store new response with same key Expected: Old response replaced with new Result: ✅ PASS - Cache entry properly updated

✅ Test 37: Cache Statistics

Action: Get cache size and keys Expected: Accurate count and key list Result: ✅ PASS - Statistics correctly reported

✅ Test 38: Clear Cache

Action: Clear all cache entries Expected: Cache size = 0 Result: ✅ PASS - All 6 entries cleared

✅ Test 39: Cache After Clear

Action: Store response after clearing Expected: Cache works normally Result: ✅ PASS - Cache functional after clear

In-Memory Cache Storage Summary

Storage: JavaScript Map object Key Format: METHOD:URL

Functions Tested:

// Store response
setCachedResponse(method, url, responseData)

// Retrieve response (returns null if not found)
getCachedResponse(method, url)

// Clear all cache (returns count of cleared entries)
clearCache()

// Get statistics (size and keys)
getCacheStats()

Response Data Structure:

{
  statusCode: 200,
  headers: { 'content-type': 'application/json', ... },
  body: '{"id":1,"title":"Product",...}'
}

Features Verified:

  • ✅ Store responses in memory (Map)
  • ✅ Retrieve cached responses
  • ✅ Handle cache misses (return null)
  • ✅ Store multiple entries
  • ✅ Separate caching by HTTP method
  • ✅ Overwrite existing entries
  • ✅ Get cache statistics
  • ✅ Clear all cache
  • ✅ Continue working after clear

✅ Test 40: Complete Response Data Storage

node test-response-storage.js

Expected: Status code, headers, and body all stored Result: ✅ PASS - All components stored and retrieved

✅ Test 41: Status Code Preservation

Status codes tested: 200, 201, 404, 500, 301, 204 Expected: All status codes preserved exactly Result: ✅ PASS - All 6 status codes match

✅ Test 42: Headers Preservation

Headers tested: 8 different headers including:

  • Standard: content-type, content-length, cache-control, etag, last-modified
  • Security: strict-transport-security
  • CORS: access-control-allow-origin
  • Custom: x-custom-header

Expected: All headers preserved with exact values Result: ✅ PASS - All headers match perfectly

✅ Test 43: Body Content Preservation

Content types tested:

  • JSON (61 chars)
  • Plain text (34 chars)
  • HTML (61 chars)
  • Empty body (0 chars)
  • Large body (10,000 chars)

Expected: All content preserved exactly Result: ✅ PASS - All body types match

✅ Test 44: Complete Structure Verification

Components verified:

  • statusCode: number type
  • headers: object type with key-value pairs
  • body: string type

Expected: Structure maintained, types correct Result: ✅ PASS - Structure and types correct

Response Data Storage Summary

Complete Response Object:

{
  statusCode: 200,                    // <number> HTTP status code
  headers: {                          // <object> All response headers
    'content-type': 'application/json',
    'cache-control': 'max-age=3600',
    'etag': 'W/"abc123"',
    // ... all other headers
  },
  body: '{"id":1,"title":"..."}'     // <string> Complete response body
}

What Gets Stored:

  1. Status Code: All HTTP status codes (2xx, 3xx, 4xx, 5xx)
  2. Headers: All headers from origin server
    • Standard headers (content-type, cache-control, etc.)
    • Security headers (HSTS, CSP, etc.)
    • CORS headers (access-control-*)
    • Custom headers (x-*)
    • Rate limiting headers
  3. Body: Complete response body
    • JSON data
    • HTML/XML
    • Plain text
    • Binary data (as string)
    • Empty bodies
    • Large payloads

Storage Verification:

  • ✅ All status codes preserved exactly
  • ✅ All headers preserved with exact values
  • ✅ All body content preserved completely
  • ✅ Data types maintained (number, object, string)
  • ✅ No data loss or corruption

✅ Test 45: Cache Policy - shouldCacheResponse Function

node test-cache-policy.js

Status codes tested: 18 different codes (2xx, 3xx, 4xx, 5xx) Expected: Only 2xx returns true Result: ✅ PASS - All 18 status codes correctly evaluated

✅ Test 46: Caching 2xx Successful Responses

Responses tested: 200, 201, 204 Expected: All cached successfully Result: ✅ PASS - 3 responses cached, cache size = 3

✅ Test 47: NOT Caching Non-2xx Responses

Responses tested: 301, 404, 500, 400 Expected: None cached, cache size unchanged Result: ✅ PASS - 0 cached, cache size remains 3

✅ Test 48: Error Responses Not Retrievable

Attempted retrievals: 404, 500 Expected: Both return null (cache miss) Result: ✅ PASS - Both not found in cache

✅ Test 49: Cache Contents Verification

Expected: Only 2xx responses in cache Result: ✅ PASS - All 3 cached responses are 2xx

✅ Test 50: Edge Cases (Boundary Testing)

Codes tested: 199, 200, 250, 299, 300 Expected: Only 200-299 cached Result: ✅ PASS - Boundaries correctly handled

Cache Policy Summary

Caching Strategy:

✅ CACHE:       2xx (200-299) - Successful responses
❌ DON'T CACHE: 3xx (300-399) - Redirects
❌ DON'T CACHE: 4xx (400-499) - Client errors  
❌ DON'T CACHE: 5xx (500-599) - Server errors

Status Codes Tested:

Code Name Cached? Result
200 OK ✅ Yes PASS
201 Created ✅ Yes PASS
202 Accepted ✅ Yes PASS
204 No Content ✅ Yes PASS
206 Partial Content ✅ Yes PASS
301 Moved Permanently ❌ No PASS
302 Found ❌ No PASS
304 Not Modified ❌ No PASS
400 Bad Request ❌ No PASS
401 Unauthorized ❌ No PASS
403 Forbidden ❌ No PASS
404 Not Found ❌ No PASS
429 Too Many Requests ❌ No PASS
500 Internal Server Error ❌ No PASS
502 Bad Gateway ❌ No PASS
503 Service Unavailable ❌ No PASS
504 Gateway Timeout ❌ No PASS

Benefits:

  • ✅ Prevents caching of errors
  • ✅ Prevents caching of redirects
  • ✅ Only stores valid, successful responses
  • ✅ Saves memory by not caching failures
  • ✅ Ensures fresh attempts for failed requests

Implementation:

function shouldCacheResponse(statusCode) {
  return statusCode >= 200 && statusCode < 300;
}

✅ Test 51: Basic Cache Retrieval

node test-cache-retrieval.js

Action: Store and retrieve a response Expected: Exact match of statusCode, headers, body Result: ✅ PASS - All components match

✅ Test 52: Cache Miss Handling

Action: Retrieve non-existent entry Expected: Returns null Result: ✅ PASS - Returns null correctly

✅ Test 53: Method-Specific Retrieval

Action: Store GET and POST to same URL, retrieve each Expected: Correct responses for each method Result: ✅ PASS - GET and POST retrieved correctly

✅ Test 54: Query Parameter Sensitivity

Action: Store responses for ?limit=10 and ?limit=20 Expected: Each returns correct response Result: ✅ PASS - Query params distinguished correctly

✅ Test 55: Case-Insensitive Method Retrieval

Action: Retrieve with "get", "GET", "Get" Expected: All return same cached response Result: ✅ PASS - All cases work, same object returned

✅ Test 56: Complete Structure Retrieval

Action: Retrieve complex response with nested objects Expected: Full structure preserved (statusCode, headers, body) Result: ✅ PASS - Complete structure intact

✅ Test 57: Multiple Retrievals (Efficiency)

Action: Retrieve same entry 5 times Expected: All successful, fast O(1) lookups Result: ✅ PASS - All 5 retrievals successful

✅ Test 58: Retrieval From Large Cache

Action: Store 5 items, retrieve specific ones Expected: Correct items retrieved Result: ✅ PASS - Items 1, 3, 5 retrieved correctly

Cache Retrieval Logic Summary

Function: getCachedResponse(method, url)

Parameters:

  • method: HTTP method (string) - case-insensitive
  • url: Complete URL (string) - including query parameters

Returns:

  • Cache HIT: { statusCode: number, headers: object, body: string }
  • Cache MISS: null

Features:

// Basic retrieval
const cached = getCachedResponse('GET', 'https://api.com/products/1');
if (cached) {
  // Cache HIT
  console.log(cached.statusCode);  // 200
  console.log(cached.headers);     // { 'content-type': '...', ... }
  console.log(cached.body);        // '{"id":1,...}'
} else {
  // Cache MISS - fetch from origin
}

Capabilities:

  1. Fast Lookups: O(1) Map-based retrieval
  2. Method-Aware: GET and POST cached separately
  3. Query-Aware: Different query params = different cache entries
  4. Case-Insensitive: Method normalization (GET, get, Get all work)
  5. Complete Data: Returns full response object
  6. Null on Miss: Clean handling of non-existent entries
  7. Logging: Logs HIT/MISS for debugging
  8. Efficient: Multiple retrievals don't degrade performance

Retrieval Examples:

// Same URL, different methods
getCachedResponse('GET', 'https://api.com/data')   // GET response
getCachedResponse('POST', 'https://api.com/data')  // POST response

// Same URL, different query params
getCachedResponse('GET', 'https://api.com/data?limit=10')  // Limit 10
getCachedResponse('GET', 'https://api.com/data?limit=20')  // Limit 20

// Case variations (all work)
getCachedResponse('get', 'https://api.com/data')
getCachedResponse('GET', 'https://api.com/data')
getCachedResponse('Get', 'https://api.com/data')

Stage 4 Complete ✅

All caching mechanism features implemented and tested:

  • ✅ Cache key generation (50 tests total)
  • ✅ In-memory storage (Map)
  • ✅ Response data storage (statusCode, headers, body)
  • ✅ Cache policy (only 2xx)
  • Cache retrieval logic (8 tests)

Stage 5 Tests - Cache Headers & Integration

✅ Test 59: X-Cache MISS Header on First Request

curl -i http://localhost:3000/products/1 | grep "x-cache:"

Expected: x-cache: MISS header present Result: ✅ PASS - X-Cache: MISS header added

✅ Test 60: X-Cache MISS with Query Parameters

curl -i "http://localhost:3000/products?limit=3" | grep "x-cache:"

Expected: x-cache: MISS header present Result: ✅ PASS - X-Cache: MISS header added

✅ Test 61: Response Cached After MISS

Server logs show:

📤 GET /products/1
📥 200 GET /products/1
💾 Cached: GET:https://dummyjson.com/products/1 (1 total entries)

Expected: Response stored in cache after fetching from origin Result: ✅ PASS - Response cached successfully

X-Cache MISS Implementation

What happens on cache MISS:

  1. ✅ Request forwarded to origin server
  2. ✅ Response received from origin
  3. X-Cache: MISS header added to response
  4. ✅ Response forwarded to client with MISS header
  5. ✅ Response stored in cache (if 2xx status code)

Headers sent to client:

HTTP/1.1 200 OK
date: Sun, 04 Jan 2026 17:29:29 GMT
content-type: application/json; charset=utf-8
...all original headers from origin...
x-cache: MISS        ← Added by proxy

Code implementation:

// Add X-Cache: MISS header
const responseHeaders = {
  ...proxyRes.headers,
  'x-cache': 'MISS'
};

res.writeHead(proxyRes.statusCode, responseHeaders);

✅ Test 62: X-Cache HIT on Second Request

# First request
curl -i http://localhost:3000/products/1 | grep "x-cache:"
# Second request to same endpoint
curl -i http://localhost:3000/products/1 | grep "x-cache:"

Expected: First = MISS, Second = HIT Result: ✅ PASS

  • First request: x-cache: MISS
  • Second request: x-cache: HIT

✅ Test 63: Multiple Cache HITs

# Third request to same endpoint
curl -i http://localhost:3000/products/1 | grep "x-cache:"

Expected: x-cache: HIT Result: ✅ PASS - Still serving from cache

✅ Test 64: Cache HIT/MISS for Different Endpoints

curl -i http://localhost:3000/products/2 | grep "x-cache:"  # MISS
curl -i http://localhost:3000/products/2 | grep "x-cache:"  # HIT

Expected: First = MISS, Second = HIT for different URL Result: ✅ PASS - Each endpoint cached independently

✅ Test 65: Cache HIT with Query Parameters

curl -i "http://localhost:3000/products?limit=3" | grep "x-cache:"  # MISS
curl -i "http://localhost:3000/products?limit=3" | grep "x-cache:"  # HIT

Expected: First = MISS, Second = HIT with query params Result: ✅ PASS - Query parameters handled correctly

X-Cache HIT Implementation

Server Logs:

❌ Cache MISS: GET:https://dummyjson.com/products/1
📤 GET /products/1
📥 200 GET /products/1
💾 Cached: GET:https://dummyjson.com/products/1 (1 total entries)

✨ Cache HIT: GET:https://dummyjson.com/products/1
✨ Serving from cache: GET /products/1

Request Flow:

Cache MISS Flow:

  1. ✅ Check cache → Not found
  2. ✅ Log "Cache MISS"
  3. ✅ Forward to origin server
  4. ✅ Receive response
  5. ✅ Add X-Cache: MISS header
  6. ✅ Forward to client
  7. ✅ Store in cache

Cache HIT Flow:

  1. ✅ Check cache → Found!
  2. ✅ Log "Cache HIT" and "Serving from cache"
  3. ✅ Add X-Cache: HIT header to cached response
  4. ✅ Send to client immediately (no origin request)

Code Implementation:

// Check cache first
const cached = getCachedResponse(req.method, fullUrl);

if (cached) {
  // Cache HIT - serve from cache
  const cachedHeaders = {
    ...cached.headers,
    'x-cache': 'HIT'
  };
  
  res.writeHead(cached.statusCode, cachedHeaders);
  res.end(cached.body);
  return;
}

// Cache MISS - forward to origin (existing flow)

Benefits:

  • ✅ Fast responses (no origin server request)
  • ✅ Reduced load on origin server
  • ✅ Clear indication via X-Cache header
  • ✅ All cached data preserved (status, headers, body)

Stage 5 Complete ✅

All cache integration features implemented:

  • ✅ X-Cache: MISS header when fetching from origin
  • ✅ Response caching after origin fetch
  • X-Cache: HIT header when serving from cache
  • ✅ Cache check before forwarding requests
  • ✅ Immediate response from cache (no origin delay)

Stage 6 Tests - Clear Cache Feature

✅ Test 66: File-Based Cache Creation

# Make requests to populate cache
curl http://localhost:3000/products/1
ls cache/

Expected: cache-data.json file created Result: ✅ PASS - File created with 12KB of cached data

✅ Test 67: Clear Cache Command

node src/index.js --clear-cache

Expected: Cache cleared with confirmation message Result: ✅ PASS

🧹 Clearing cache...
   Current cache size: 3 entries

   Cached entries:
     1. GET:https://dummyjson.com/products/1
     2. GET:https://dummyjson.com/products/2
     3. GET:https://dummyjson.com/products?limit=3

✅ Cache cleared successfully!
   3 entries removed

✅ Test 68: Cache File Deleted

ls cache/

Expected: cache-data.json file deleted Result: ✅ PASS - File removed, directory empty

✅ Test 69: Requests After Clear (MISS)

curl -i http://localhost:3000/products/1 | grep "x-cache:"

Expected: x-cache: MISS (cache was cleared) Result: ✅ PASS - Shows MISS

✅ Test 70: Caching Still Works After Clear

curl -i http://localhost:3000/products/1 | grep "x-cache:"  # Second request

Expected: x-cache: HIT (re-cached) Result: ✅ PASS - Shows HIT

Clear Cache Implementation

File-Based Storage:

  • Cache stored in cache/cache-data.json
  • JSON format for easy inspection
  • Persistent across server runs
  • Shared between server and --clear-cache command

Cache Functions:

loadCache()    // Read cache from file
saveCache()    // Write cache to file
clearCache()   // Delete cache file

Clear Cache Command:

caching-proxy --clear-cache

Features:

  • ✅ Shows cache size before clearing
  • ✅ Lists cached entries (first 5 + count)
  • ✅ Deletes cache file
  • ✅ Confirms successful clearing
  • ✅ Handles empty cache gracefully

Stage 6 Complete ✅

All clear cache features implemented:

  • ✅ File-based persistent cache storage
  • ✅ --clear-cache command
  • ✅ User-friendly output
  • ✅ Cache statistics display
  • ✅ Proper file deletion

Stage 8: Production Caching Enhancements Testing ✅

Test 1: Cache Only GET Requests

Purpose: Verify only GET requests are cached, not POST/PUT/DELETE

Command:

# GET request (should cache)
curl -s http://localhost:3000/products/10
curl -s -i http://localhost:3000/products/10 | grep "x-cache:"

Expected Result:

x-cache: HIT

Actual Result: ✅ PASS

  • First request: MISS (fetched from origin)
  • Second request: HIT (served from cache)
  • POST/PUT/DELETE requests not cached (method check works)

Test 2: Avoid Authenticated Requests

Purpose: Don't cache requests with Authorization headers or cookies

Command:

# With Authorization header (should NOT cache)
curl -s -H "Authorization: Bearer token123" http://localhost:3000/products/11
curl -s -H "Authorization: Bearer token123" -i http://localhost:3000/products/11 | grep "x-cache:"

Expected Result:

x-cache: MISS

Actual Result: ✅ PASS

  • Both requests returned MISS (not cached)
  • Security check prevents caching authenticated requests
  • Prevents data leakage between users

Test 3: Respect Cache-Control Headers

Purpose: Don't cache if origin says Cache-Control: no-store, no-cache, or private

Command:

# Check origin's Cache-Control
curl -s -i https://dummyjson.com/products/1 | grep -i "cache-control"

# Request through proxy (should NOT cache)
curl -s http://localhost:3000/products/1
curl -s -i http://localhost:3000/products/1 | grep "x-cache:"

Expected Result:

Cache-Control: no-store
x-cache: MISS

Actual Result: ✅ PASS

  • Origin returns Cache-Control: no-store
  • Proxy respects it and doesn't cache
  • Both requests returned MISS
  • HTTP spec compliance verified

Test 4: Cache TTL (5 minutes)

Purpose: Cached entries expire after 5 minutes

Command:

# Cache an entry
curl -s http://localhost:3000/products/5

# Check TTL
node -e "
const fs = require('fs');
const data = JSON.parse(fs.readFileSync('cache/cache-data.json', 'utf8'));
Object.entries(data).forEach(([key, value]) => {
  const ttlMs = value.expiresAt - Date.now();
  const ttlMin = Math.floor(ttlMs / 60000);
  const ttlSec = Math.floor((ttlMs % 60000) / 1000);
  console.log(\`\${key} | TTL: \${ttlMin}m \${ttlSec}s\`);
});
"

Expected Result:

GET:https://dummyjson.com/products/5 | TTL: 4m 58s

Actual Result: ✅ PASS

  • Cached entries have cachedAt and expiresAt timestamps
  • TTL is 5 minutes (300000ms)
  • Server logs show: 💾 Cached: ... (TTL: 5min, 2 total entries)
  • Expired entries auto-removed on retrieval

Test 5: Comprehensive Integration Test

Purpose: Verify all 4 enhancements work together

Command:

echo "=== COMPREHENSIVE FINAL TEST ==="

# Task #1: GET only
curl -s http://localhost:3000/products/10 > /dev/null
curl -s -i http://localhost:3000/products/10 | grep "x-cache:"

# Task #2: No Auth
curl -s -H "Authorization: Bearer test" http://localhost:3000/products/11 > /dev/null
curl -s -H "Authorization: Bearer test" -i http://localhost:3000/products/11 | grep "x-cache:"

# Task #3: Cache-Control
curl -s http://localhost:3000/products/1 > /dev/null
curl -s -i http://localhost:3000/products/1 | grep "x-cache:"

# Task #4: TTL Check
node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync('cache/cache-data.json','utf8')); console.log('Entries:', Object.keys(data).length);"

Expected Result:

x-cache: HIT     (GET request cached)
x-cache: MISS    (Auth request not cached)
x-cache: MISS    (Cache-Control: no-store not cached)
Entries: 2       (Only valid entries cached)

Actual Result: ✅ PASS

  • All 4 caching strategies working correctly
  • Production-ready caching behavior verified
  • Security and HTTP spec compliance confirmed

Summary

All Features Tested ✅

  • ✅ CLI argument parsing
  • ✅ Port validation
  • ✅ URL validation
  • ✅ HTTP/HTTPS proxy forwarding
  • ✅ All HTTP methods (GET, POST, PUT, DELETE, etc.)
  • ✅ Request preservation (headers, query params, body)
  • ✅ Response caching (status, headers, body)
  • ✅ Cache key generation (METHOD:URL)
  • ✅ Cache HIT/MISS headers
  • ✅ Clear cache functionality
  • Cache only GET requests (production enhancement)
  • Avoid authenticated requests (security enhancement)
  • Respect Cache-Control headers (HTTP spec compliance)
  • Cache TTL (5 minutes) (prevent stale data)

Production Readiness

  • ✅ Secure caching (no auth data leakage)
  • ✅ HTTP spec compliant (Cache-Control respected)
  • ✅ Stale data prevention (TTL expiration)
  • ✅ Standard caching practice (GET only)

Next Testing Phase

All testing phases complete! Project is production-ready.