Version: 2.0.0
Date: March 30, 2026
Status: In Progress
This document outlines a comprehensive refactoring and feature enhancement plan for TinyProxy, transforming it from a basic PHP proxy into a production-ready, modern PHP 8.5+ application with enterprise-grade features.
- ✅ Complete code restructure with PSR-4 autoloading
- ✅ Critical security hardening (SSRF, rate limiting, access control)
- ✅ Enhanced caching system with LRU eviction
- ✅ RESTful API with authentication
- ✅ Admin dashboard for management
- ✅ Comprehensive testing suite (80%+ coverage)
- ✅ Performance optimizations
Estimated Duration: 4 weeks
Complexity: High
Impact: Transformational
- Language: PHP 8.5.4
- Dependencies: Guzzle HTTP Client 7.8
- Architecture: Procedural with basic OOP
- Structure: Flat file structure, no namespaces
- Security: Basic (needs critical improvements)
- Testing: None
- Documentation: Basic README
⚠️ SSRF Vulnerability: Open proxy can access internal networks (127.0.0.1, 10.x.x.x, 192.168.x.x)⚠️ No Rate Limiting: Susceptible to abuse and DDoS⚠️ No Authentication: Anyone can use the proxy⚠️ XSS in Debug Output:debug.php:16outputs unescaped content⚠️ Insecure Permissions: Cache directory uses 0777 permissions⚠️ Error Suppression:@includeand@loadHTMLhide security issues
- ❌ No autoloading - manual
requirestatements - ❌ No namespaces - risk of class name collisions
- ❌ Global constants via
define()- hard to test/mock - ❌ Tight coupling between components
- ❌ No dependency injection
- ❌ Mixed concerns (business logic + presentation)
- No type hints on most methods
- No return type declarations
- No interfaces for abstractions
- Duplicate URL conversion logic
- Inconsistent error handling
- No validation of configuration values
- No cache size management - unlimited growth
- No cache cleanup mechanism
- Synchronous HTTP requests only
- No compression support
- Loading entire responses into memory
- No authentication/authorization
- No API endpoints
- No admin panel
- No statistics/monitoring
- No request logging (errors only)
- No testing infrastructure
Priority: HIGH | Effort: Medium | Duration: Week 1
tinyproxy/
├── config/ # Configuration files
├── public/ # Web-accessible files only
│ ├── index.php # Main entry point
│ ├── api.php # API entry point
│ ├── admin/ # Admin dashboard
│ └── assets/ # CSS, JS, images
├── src/ # Application source code
│ ├── Bootstrap.php
│ ├── Container.php
│ ├── Cache/
│ ├── Config/
│ ├── Core/
│ ├── Http/
│ ├── Modifier/
│ ├── Security/
│ ├── Logger/
│ ├── Api/
│ ├── Admin/
│ ├── Statistics/
│ ├── Exception/
│ └── Util/
├── templates/ # View templates
├── tests/ # Test suites
│ ├── Unit/
│ └── Integration/
├── var/ # Variable data (cache, logs)
│ ├── cache/
│ └── logs/
├── vendor/ # Composer dependencies
├── .env.example # Environment configuration template
└── composer.json # Dependency management
New Dependencies:
vlucas/phpdotenv- Environment configurationpsr/log- Logging interfacepsr/container- DI container interfacesymfony/cache- Advanced caching componentsleague/uri- Safe URL parsing
Dev Dependencies:
phpunit/phpunit- Testing frameworkphpstan/phpstan- Static analysissquizlabs/php_codesniffer- Code stylepsalm/psalm- Additional static analysisfakerphp/faker- Test data generation
{
"autoload": {
"psr-4": {
"TinyProxy\\": "src/"
}
}
}Priority: CRITICAL | Effort: High | Duration: Week 1
Implementation: src/Security/UrlValidator.php
Features:
- Block private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- Block localhost (127.0.0.1, ::1)
- Block link-local addresses (169.254.0.0/16)
- Block cloud metadata endpoints (169.254.169.254)
- Domain whitelist/blacklist support
- DNS rebinding protection
- Maximum redirect limit
- Only allow http/https schemes
Example:
$validator = new UrlValidator($config);
if (!$validator->isValid($url)) {
throw new SecurityException('Invalid or prohibited URL');
}Implementation: src/Security/RateLimiter.php
Features:
- Per-IP rate limits (e.g., 100 requests/minute)
- Per-API-key rate limits (e.g., 1000 requests/hour)
- Sliding window algorithm
- APCu for fast storage (no external dependencies)
- Configurable limits per endpoint
- Rate limit headers (X-RateLimit-*)
Example:
$rateLimiter = new RateLimiter($cache);
if (!$rateLimiter->check($identifier, $limit, $window)) {
throw new SecurityException('Rate limit exceeded');
}Implementation: src/Security/AccessControl.php
Features:
- API key authentication
- JWT tokens for admin panel
- IP whitelist/blacklist
- Role-based access control (RBAC)
- Token expiration and refresh
- Secure token generation
Example:
$accessControl = new AccessControl($config);
if (!$accessControl->authenticate($request)) {
throw new SecurityException('Unauthorized');
}- Validate all GET/POST parameters
- Escape HTML output in templates
- Remove
@error suppression - Implement proper CSP headers
- Sanitize log output to prevent log injection
Priority: HIGH | Effort: High | Duration: Week 1-2
Implementation: src/Container.php (PSR-11 compatible)
Features:
- Auto-wiring of dependencies
- Singleton and factory support
- Interface binding
- Lazy loading
Example:
$container = new Container();
$container->bind(CacheInterface::class, FileCache::class);
$container->bind(LoggerInterface::class, FileLogger::class);
$proxy = $container->make(ProxyService::class);Implementation: src/Config/Configuration.php
Features:
- Load from
.envfile - Environment-specific configs (dev, staging, prod)
- Type-safe getters with validation
- Default values
- Config caching for performance
- Hot-reload capability
Example:
$config = new Configuration();
$cacheDir = $config->getString('CACHE_DIRECTORY', 'var/cache');
$cacheDuration = $config->getInt('CACHE_DURATION', 3600);Strict Types (PHP 7.0+):
<?php
declare(strict_types=1);Constructor Property Promotion (PHP 8.0+):
public function __construct(
private CacheInterface $cache,
private LoggerInterface $logger,
private UrlValidator $validator
) {}Named Arguments (PHP 8.0+):
$proxy->proxyRequest(
targetUrl: $url,
useCache: true,
modifyContent: true
);Match Expressions (PHP 8.0+):
$processor = match($contentType) {
'text/html' => $this->htmlModifier,
'text/css' => $this->cssModifier,
default => null
};Enum Classes (PHP 8.1+):
enum CacheStrategy: string {
case AGGRESSIVE = 'aggressive';
case NORMAL = 'normal';
case MINIMAL = 'minimal';
}Readonly Properties (PHP 8.1+):
class Config {
public function __construct(
public readonly string $cacheDir,
public readonly int $cacheDuration
) {}
}Key Interfaces:
interface CacheInterface {
public function get(string $key): ?CachedContent;
public function set(string $key, CachedContent $content): void;
public function has(string $key): bool;
public function delete(string $key): void;
public function clear(): void;
}
interface ModifierInterface {
public function modify(string $content, string $baseUrl): string;
public function supports(string $contentType): bool;
}
interface LoggerInterface {
public function log(string $level, string $message, array $context = []): void;
}Priority: HIGH | Effort: Medium | Duration: Week 2
- LRU Eviction: Remove least recently used when size limit reached
- Cache Metadata: Track hits, misses, size, last access time
- Selective Clearing: Clear by pattern, domain, or age
- Statistics: Hit rate, total size, entry count
- Compression: gzip cached content to save disk space
- TTL per Type: Different durations for different content types
- Cache Warming: Pre-cache popular URLs
var/cache/
├── content/
│ ├── ab/
│ │ └── abc123.cache.gz # Compressed cached content
│ └── cd/
│ └── cde456.cache.gz
└── metadata/
├── index.json # LRU tracking, statistics
└── entries/
├── abc123.meta.json # Individual entry metadata
└── cde456.meta.json
$cacheManager = new CacheManager($cache, $config);
// Get statistics
$stats = $cacheManager->getStatistics();
// ['hits' => 1234, 'misses' => 56, 'size' => 12345678, 'count' => 100]
// Clear by pattern
$cacheManager->clearByPattern('*.example.com');
// Clear by age
$cacheManager->clearOlderThan(86400); // 24 hours
// Get cache info
$info = $cacheManager->getEntryInfo($key);Priority: MEDIUM | Effort: Medium | Duration: Week 2-3
Authentication Required: X-API-Key header or JWT token
GET /api/health # System health check
GET /api/stats # Overall statistics
GET /api/stats/cache # Cache-specific stats
GET /api/stats/requests # Request statistics
GET /api/cache # List cache entries
GET /api/cache/:key # Get cache entry info
DELETE /api/cache/:key # Delete cache entry
POST /api/cache/clear # Clear entire cache
POST /api/cache/clear/:pattern # Clear by pattern
GET /api/logs # Get recent logs
GET /api/logs/:type # Get logs by type (access/error/debug)
GET /api/config # Get current configuration
POST /api/config # Update configuration
POST /api/auth/login # Admin login
POST /api/auth/logout # Admin logout
POST /api/auth/refresh # Refresh JWT token
GET /api/blacklist # Get blacklisted domains
POST /api/blacklist # Add domain to blacklist
DELETE /api/blacklist/:domain # Remove from blacklist
GET /api/whitelist # Get whitelisted domains
POST /api/whitelist # Add domain to whitelist
DELETE /api/whitelist/:domain # Remove from whitelist
- CORS Middleware - Handle cross-origin requests
- Authentication Middleware - Verify API key/JWT
- Rate Limit Middleware - Enforce rate limits
- Logging Middleware - Log all API requests
{
"success": true,
"data": {
"cache_hits": 1234,
"cache_misses": 56
},
"meta": {
"timestamp": 1234567890,
"version": "2.0.0"
}
}Error Response:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 60 seconds.",
"details": {
"limit": 100,
"window": 60,
"retry_after": 60
}
}
}Priority: MEDIUM | Effort: Medium | Duration: Week 3
Overview Page:
- Real-time statistics (requests, cache hits, bandwidth)
- System health indicators
- Recent requests log
- Error rate graphs
Cache Management:
- Browse cache entries with search/filter
- View cache entry details (content type, size, age, hits)
- Delete individual entries
- Clear cache by pattern/domain
- Cache size visualization
Log Viewer:
- Access logs with filters (date, IP, URL)
- Error logs with severity levels
- Search and export logs
- Real-time log streaming
Configuration Editor:
- Edit settings via web UI
- Validation before saving
- Restart/reload required indicators
Domain Management:
- Add/remove blacklisted domains
- Add/remove whitelisted domains
- Test URL accessibility
Statistics & Analytics:
- Request volume over time (Chart.js)
- Cache hit rate trends
- Top requested domains
- Bandwidth usage
- Response time metrics
User Management:
- Create/edit admin users
- Manage API keys
- View API usage per key
- Frontend: Vanilla JavaScript (no framework)
- Charts: Chart.js for visualizations
- Styling: Custom CSS with CSS Grid/Flexbox
- Real-time: Server-Sent Events (SSE) or WebSocket
- Authentication: JWT tokens
- JWT authentication required
- CSRF protection
- XSS prevention (escape all output)
- Rate limiting on login attempts
- Session timeout
Priority: MEDIUM | Effort: High | Duration: Week 4
Test Structure:
tests/Unit/
├── Cache/
│ ├── FileCacheTest.php
│ ├── CacheManagerTest.php
│ └── LRUEvictionStrategyTest.php
├── Security/
│ ├── RateLimiterTest.php
│ ├── UrlValidatorTest.php
│ ├── AccessControlTest.php
│ └── AuthenticatorTest.php
├── Modifier/
│ ├── HtmlModifierTest.php
│ ├── CssModifierTest.php
│ └── AdBlockerTest.php
├── Config/
│ └── ConfigurationTest.php
└── Util/
└── UrlHelperTest.php
Example Test:
class UrlValidatorTest extends TestCase
{
public function testBlocksPrivateIpAddresses(): void
{
$validator = new UrlValidator($this->config);
$this->assertFalse($validator->isValid('http://127.0.0.1'));
$this->assertFalse($validator->isValid('http://192.168.1.1'));
$this->assertFalse($validator->isValid('http://10.0.0.1'));
}
public function testAllowsPublicUrls(): void
{
$validator = new UrlValidator($this->config);
$this->assertTrue($validator->isValid('https://example.com'));
}
}Test Scenarios:
- Complete proxy request flow
- Cache hit/miss scenarios
- Content modification pipeline
- API endpoint responses
- Authentication flow
- Rate limiting behavior
- SSRF vulnerability prevention
- XSS attack prevention
- Rate limit enforcement
- Authentication bypass attempts
- SQL injection (if database added)
- PHPStan Level 8: Strictest analysis
- Psalm: Additional type checking
- PHP CodeSniffer: PSR-12 compliance
- PHP Mess Detector: Code quality metrics
Priority: LOW | Effort: Medium | Duration: Week 4
// ETag support
$etag = md5($content);
header("ETag: \"{$etag}\"");
// Last-Modified
$lastModified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
header("Last-Modified: {$lastModified}");
// 304 Not Modified
if ($request->getHeader('If-None-Match') === $etag) {
http_response_code(304);
exit;
}- gzip/deflate for text content
- Brotli compression support
- Automatic compression based on Accept-Encoding
// Stream large files instead of loading into memory
$stream = $response->getBody();
while (!$stream->eof()) {
echo $stream->read(8192);
flush();
}- Reuse Guzzle HTTP connections
- Keep-alive connections
- DNS caching
- OPcache for PHP bytecode
- APCu for in-memory data
- Cache preloading for popular sites
// On-the-fly image resizing
$optimizer = new ImageOptimizer();
$optimized = $optimizer->resize($image, $width, $height);
// WebP conversion for supported browsers
if ($request->acceptsWebP()) {
$webp = $optimizer->convertToWebP($image);
}| Phase | Priority | Effort | Impact | Week | Status |
|---|---|---|---|---|---|
| Phase 2: Security | 🔴 CRITICAL | High | High | 1 | Pending |
| Phase 1: Structure | 🟠 HIGH | Medium | High | 1 | Pending |
| Phase 3: Refactoring | 🟠 HIGH | High | Medium | 1-2 | Pending |
| Phase 4: Caching | 🟠 HIGH | Medium | Medium | 2 | Pending |
| Phase 5: API | 🟡 MEDIUM | Medium | Medium | 2-3 | Pending |
| Phase 6: Dashboard | 🟡 MEDIUM | Medium | Medium | 3 | Pending |
| Phase 7: Testing | 🟡 MEDIUM | High | High | 4 | Pending |
| Phase 8: Performance | 🟢 LOW | Medium | Low | 4 | Pending |
These can be implemented quickly for immediate impact:
- Add strict types to all PHP files (30 minutes)
- Block private IP ranges in URL validation (15 minutes)
- Fix cache permissions from 0777 to 0755 (5 minutes)
- Remove @ error suppression (20 minutes)
- Add .env file support (10 minutes)
- Implement basic rate limiting with APCu (1 hour)
- Escape HTML in debug output (5 minutes)
- Add PSR-4 autoloading (10 minutes)
Total Time: ~2 hours
Impact: Significant security and code quality improvements
- ✅ SSRF vulnerability fixed
- ✅ Rate limiting implemented
- ✅ PSR-4 autoloading
- ✅ Type hints on all methods
- ✅ LRU cache eviction
- ✅ Basic API endpoints
- ✅ Unit test coverage >50%
- ✅ Admin dashboard
- ✅ API authentication
- ✅ Enhanced cache manager
- ✅ Request logging
- ✅ Static analysis (PHPStan level 8)
- ✅ Unit test coverage >80%
- ✅ Real-time dashboard updates
- ✅ Image optimization
- ✅ Performance benchmarks
- ✅ CI/CD pipeline
- ✅ Docker compose setup
- Keep old files during migration
- Create
legacy/directory for old code - Run old and new code side-by-side initially
- Gradual feature flag rollout
- Stage 1: Set up new structure without touching old code
- Stage 2: Implement security fixes in new code
- Stage 3: Migrate core functionality
- Stage 4: Add new features (API, dashboard)
- Stage 5: Remove old code after validation
- Git tags for each phase
- Database backups (if added)
- Quick rollback script
- Feature flags for new functionality
- Updated installation instructions
- New configuration options
- API documentation
- Docker deployment guide
- Performance tuning tips
- Version 2.0.0 changes
- Breaking changes list
- Migration guide from 1.x
- System architecture diagrams
- Component interaction flow
- Class diagrams
- Sequence diagrams
- Complete API reference
- Authentication guide
- Code examples
- Response schemas
- Development setup
- Coding standards
- Testing requirements
- Pull request process
- PHP 8.1+ (8.5 recommended)
- Composer 2.x
- Git
- Docker (optional, for containerization)
- PHPStorm: With PHP Inspections plugin
- VSCode: With PHP Intelephense extension
- EditorConfig: For consistent formatting
- Xdebug: For debugging and coverage
# Run tests
composer test
# Static analysis
composer phpstan
# Code style check
composer phpcs
# Code style fix
composer phpcbf
# All checks
composer check- Test Coverage: Target >80%
- PHPStan Level: Level 8 (max)
- Code Complexity: Cyclomatic complexity <10
- Documentation: 100% of public methods
- Response Time: <100ms for cached requests
- Cache Hit Rate: >70%
- Memory Usage: <64MB per request
- Throughput: >1000 req/sec (with cache)
- Known Vulnerabilities: 0
- OWASP Top 10: All mitigated
- Security Headers Score: A+ (securityheaders.com)
- SSL Labs Rating: A+ (if using HTTPS)
- Monitor error logs daily
- Review security alerts
- Performance profiling weekly
- Dependency updates monthly
- Security patches immediately
- GitHub Issues for bug reports
- Discussions for feature requests
- Pull requests welcome
- Code of conduct enforcement
This refactoring plan maintains the MIT License of the original project.
This plan has been reviewed and approved for implementation.
Author: OpenCode AI Assistant
Date: March 30, 2026
Version: 1.0
Next Steps: Begin Phase 1 implementation with directory structure setup and composer configuration.