{"id":28499528,"url":"https://github.com/faizancodes/secure-server-fetch","last_synced_at":"2026-02-04T16:32:57.809Z","repository":{"id":268949720,"uuid":"905945184","full_name":"faizancodes/secure-server-fetch","owner":"faizancodes","description":"A secure, server-side HTTP client with built-in API key validation, rate limiting, and security features.","archived":false,"fork":false,"pushed_at":"2024-12-21T06:57:46.000Z","size":148,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-26T04:51:49.673Z","etag":null,"topics":["api-key-authentication","fetch-api","rate-limiting"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/secure-server-fetch","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/faizancodes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-19T20:36:45.000Z","updated_at":"2024-12-21T06:57:49.000Z","dependencies_parsed_at":"2024-12-19T22:41:59.846Z","dependency_job_id":"f604606c-a03f-49f4-b177-b4ce1e38667b","html_url":"https://github.com/faizancodes/secure-server-fetch","commit_stats":null,"previous_names":["faizancodes/secure-server-fetch"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/faizancodes/secure-server-fetch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faizancodes%2Fsecure-server-fetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faizancodes%2Fsecure-server-fetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faizancodes%2Fsecure-server-fetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faizancodes%2Fsecure-server-fetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/faizancodes","download_url":"https://codeload.github.com/faizancodes/secure-server-fetch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faizancodes%2Fsecure-server-fetch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29090611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T03:31:03.593Z","status":"ssl_error","status_checked_at":"2026-02-04T03:29:50.742Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-key-authentication","fetch-api","rate-limiting"],"created_at":"2025-06-08T14:36:35.786Z","updated_at":"2026-02-04T16:32:57.793Z","avatar_url":"https://github.com/faizancodes.png","language":"TypeScript","readme":"# Secure Server Fetch\n\nA secure, server-side HTTP client with built-in API key validation, rate limiting, and security features.\n\n## Features\n\n- 🔒 Server-side only execution\n- 🔑 API key validation and requirement\n- ⏱️ Rate limiting with Redis\n- 🔐 HTTPS enforcement\n- ⚡ Request timeout handling\n- 🛡️ Comprehensive error handling\n\n## Installation\n\n```bash\nnpm install secure-server-fetch\n# or\nyarn add secure-server-fetch\n```\n\n## Environment Variables Setup\n\nCreate a `.env` file in your project root:\n\n```env\nUPSTASH_REDIS_REST_URL=your_redis_url\nUPSTASH_REDIS_REST_TOKEN=your_redis_token\n```\n\nBoth variables are required for rate limiting functionality. The Redis URL must be a valid HTTPS URL.\n\n## Usage Examples\n\n### Basic Fetch with API Key\n\n```typescript\nimport { secureServerFetch } from 'secure-server-fetch';\n\nasync function fetchData() {\n  try {\n    const data = await secureServerFetch('https://api.example.com/data', {\n      apiKey: 'your-api-key',\n      timeout: 5000, // 5 seconds\n    });\n    return data;\n  } catch (error) {\n    console.error('Fetch failed:', error);\n  }\n}\n```\n\n### API Key Validation\n\n```typescript\nimport { requireApiKey } from 'secure-server-fetch';\n\n// In your API route handler\nexport async function handler(request: Request) {\n  const apiKeyCheck = requireApiKey(request, 'your-expected-api-key');\n  if (apiKeyCheck) {\n    return apiKeyCheck; // Returns 401 response if validation fails\n  }\n  \n  // Continue with your API logic\n}\n```\n\n#### API Key Requirements\n\nThe API key validation enforces the following requirements:\n\n- **Length**: Must be at least 32 characters long\n- **Character Set**: Can only contain:\n  - Uppercase letters (A-Z)\n  - Lowercase letters (a-z)\n  - Numbers (0-9)\n  - Underscores (_)\n  - Hyphens (-)\n- **Character Mix**: Must contain at least:\n  - One uppercase letter\n  - One lowercase letter\n  - One number\n\n#### Error Responses\n\nAll error responses are returned in JSON format with appropriate HTTP status codes:\n\n1. **Missing API Key** (Status: 401)\n```json\n{\n  \"error\": \"API key is missing\",\n  \"message\": \"Please provide 'x-api-key' header with a valid API key\",\n  \"requirements\": {\n    \"format\": \"Must be at least 32 characters long\",\n    \"characters\": \"Can only contain letters, numbers, underscores, and hyphens\",\n    \"complexity\": \"Must contain at least one uppercase letter, one lowercase letter, and one number\"\n  }\n}\n```\n\n2. **Empty API Key** (Status: 401)\n```json\n{\n  \"error\": \"Empty API key\",\n  \"message\": \"API key cannot be empty\",\n  \"requirements\": {\n    \"format\": \"Must be at least 32 characters long\",\n    \"characters\": \"Can only contain letters, numbers, underscores, and hyphens\",\n    \"complexity\": \"Must contain at least one uppercase letter, one lowercase letter, and one number\"\n  }\n}\n```\n\n3. **Invalid Format** (Status: 401)\n```json\n{\n  \"error\": \"Invalid API key format\",\n  \"message\": \"[Specific validation error message]\",\n  \"requirements\": {\n    \"format\": \"Must be at least 32 characters long\",\n    \"characters\": \"Can only contain letters, numbers, underscores, and hyphens\",\n    \"complexity\": \"Must contain at least one uppercase letter, one lowercase letter, and one number\"\n  }\n}\n```\n\n4. **Invalid API Key** (Status: 401)\n```json\n{\n  \"error\": \"Invalid API key\",\n  \"message\": \"The provided API key is not valid\"\n}\n```\n\n### Rate Limiting\n\n```typescript\nimport { rateLimit } from 'secure-server-fetch';\n\nasync function handleRequest(request: Request) {\n  try {\n    const rateLimitResult = await rateLimit(request, 'unique-identifier', {\n      maxRequests: 100,\n      timeframeMs: 60000, // 1 minute\n    });\n\n    // Rate limit headers will be automatically included in rateLimitResult.headers\n    \n    // Your API logic here\n    \n  } catch (error) {\n    if (error.name === 'RateLimitError') {\n      return new Response('Rate limit exceeded', { status: 429 });\n    }\n  }\n}\n```\n\n## API Reference\n\n### secureServerFetch(url, options)\n\nMakes a secure server-side HTTP request.\n\n#### Options\n\n- `apiKey?: string` - API key for authentication\n- `requireHttps?: boolean` - Enforce HTTPS (default: true)\n- `timeout?: number` - Request timeout in ms (default: 30000)\n- `...RequestInit` - All standard fetch options\n\n### requireApiKey(request, expectedKey)\n\nValidates API key from request headers.\n\n- `request: Request` - Incoming request object\n- `expectedKey: string` - The API key to validate against\n\n### rateLimit(request, identifier, options)\n\nImplements rate limiting for requests.\n\n#### Options\n\n- `maxRequests: number` - Maximum requests allowed\n- `timeframeMs: number` - Time window in milliseconds\n- `prefix?: string` - Redis key prefix\n\n## Security Best Practices\n\n1. **API Keys**\n   - Use keys at least 32 characters long\n   - Include mix of uppercase, lowercase, and numbers\n   - Rotate keys periodically\n   - Store keys securely in environment variables\n\n2. **Rate Limiting**\n   - Implement rate limiting on all public endpoints\n   - Use unique identifiers (e.g., IP, user ID)\n   - Set appropriate limits based on endpoint sensitivity\n\n3. **HTTPS**\n   - Always use HTTPS in production\n   - Only disable HTTPS requirement in development\n\n4. **Error Handling**\n   - Never expose internal errors to clients\n   - Use provided error classes for consistent handling\n   - Log errors securely\n\n## Error Handling\n\nThe library provides specific error classes:\n\n- `ServerSideError`: For client-side execution attempts\n- `NetworkError`: For network and HTTP errors\n- `ValidationError`: For input validation failures\n- `RateLimitError`: For rate limit violations\n\n## Contributing\n\nContributions are welcome! Please read our contributing guidelines and submit pull requests.\n\n## License\n\nMIT ","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaizancodes%2Fsecure-server-fetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaizancodes%2Fsecure-server-fetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaizancodes%2Fsecure-server-fetch/lists"}