Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Http Server Laravel Package

amphp/http-server

Non-blocking, concurrent HTTP/1.1 and HTTP/2 application server for PHP 8.1+ built on Revolt and Amp (fibers). Includes TLS, middleware, gzip, and integrations for routing, static files, WebSockets, sessions, and more.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require amphp/http-server
    
  2. Basic server initialization (in bootstrap.php or similar):
    use Amp\Http\Server\SocketHttpServer;
    use Amp\Http\Server\RequestHandler;
    use Amp\Http\Server\Response;
    use Amp\Http\HttpStatus;
    use Amp\Log\ConsoleLogger;
    
    $logger = new ConsoleLogger();
    $server = SocketHttpServer::createForDirectAccess($logger);
    
    $requestHandler = new class implements RequestHandler {
        public function handleRequest(Request $request): Response {
            return new Response(
                status: HttpStatus::OK,
                headers: ['Content-Type' => 'text/plain'],
                body: 'Hello, AMPHP!'
            );
        }
    };
    
    $server->expose('127.0.0.1:8080');
    $server->start($requestHandler, new DefaultErrorHandler());
    
  3. Run the server (in index.php or CLI entrypoint):
    Amp\run(function () use ($server) {
        Amp\trapSignal([SIGINT, SIGTERM], function () {
            $server->stop();
        });
    });
    

First Use Case: Static File Serving

For a quick static file server, combine with amphp/http-server-static-content:

composer require amphp/http-server-static-content
use Amp\Http\Server\StaticContent\StaticContentHandler;

$staticHandler = new StaticContentHandler(__DIR__.'/public');
$server->start($staticHandler, new DefaultErrorHandler());

Implementation Patterns

Request Handling Workflow

  1. Middleware Pipeline:
    $handler = Middleware\stackMiddleware(
        $coreHandler,
        new LoggingMiddleware(),
        new AuthMiddleware(),
        new RateLimitMiddleware()
    );
    
  2. Async Database Operations (using amphp/mysql):
    $db = new Amp\Mysql\Connection('mysql:host=localhost;dbname=test');
    $requestHandler = new class($db) implements RequestHandler {
        public function handleRequest(Request $request): Response {
            $result = Amp\async(function () {
                return $this->db->query('SELECT * FROM users WHERE id = ?', [$request->getUri()->getQuery()]);
            });
            return new Response(body: json_encode($result->await()));
        }
    };
    

Routing with amphp/http-server-router

use Amp\Http\Server\Router;

$router = new Router();
$router->addRoute('GET', '/users', new UsersHandler());
$router->addRoute('POST', '/users', new UserCreateHandler());

$server->start($router, new DefaultErrorHandler());

WebSocket Integration

use Amp\Websocket\Server\WebsocketServer;

$websocketHandler = new class implements WebsocketServer {
    public function onOpen(Connection $connection): void { /* ... */ }
    public function onMessage(Connection $connection, string $message): void { /* ... */ }
    // ...
};

$server->addWebsocketHandler('/ws', $websocketHandler);

File Uploads

$uploadHandler = new class implements RequestHandler {
    public function handleRequest(Request $request): Response {
        $body = Amp\async(function () use ($request) {
            return $request->getBody()->buffer();
        });

        $file = fopen('uploads/' . uniqid() . '.tmp', 'wb');
        fwrite($file, $body->await());
        fclose($file);

        return new Response(status: HttpStatus::OK);
    }
};

Gotchas and Tips

Common Pitfalls

  1. Blocking I/O:

    • Bad: file_get_contents($url) (blocks the event loop).
    • Good: Use Amp\Http\Client\request() or Amp\File\open().
    • Debug Tip: If requests hang, check for synchronous sleep(), file_get_contents(), or database queries.
  2. Memory Leaks:

    • Unclosed streams (e.g., fopen() without fclose()) or unbuffered responses can leak memory.
    • Fix: Always await() async operations or use Amp\ByteStream\close().
  3. Middleware Order:

    • Middleware runs top-to-bottom in stackMiddleware(). Auth should typically run before logging to avoid logging unauthorized requests.

Debugging Tips

  1. Log Requests:

    $loggerMiddleware = new class implements Middleware {
        public function handleRequest(Request $request, RequestHandler $next): Response {
            \Amp\Log\error('Incoming request: ' . $request->getMethod() . ' ' . $request->getUri());
            return $next->handleRequest($request);
        }
    };
    
  2. Slow Requests:

    • Use Amp\Time\delay() to simulate async delays:
      Amp\delay(1000); // 1-second delay (non-blocking)
      
  3. HTTP/2 Issues:

    • Ensure nghttp2 is installed (pecl install nghttp2).
    • Disable HTTP/2 for testing:
      $server = SocketHttpServer::createForDirectAccess($logger, [
          'http2' => false,
      ]);
      

Performance Optimizations

  1. Connection Pooling:

    • Reuse Client instances for repeated requests:
      $client = new Amp\Http\Client\Client();
      $server->setClientFactory(function () use ($client) {
          return $client;
      });
      
  2. Gzip Compression:

    • Enable globally:
      $server = SocketHttpServer::createForDirectAccess($logger, [
          'compression' => true,
      ]);
      
    • Or per-response:
      $response = new Response(..., ['Content-Encoding' => 'gzip']);
      
  3. Concurrency Limits:

    • Adjust limits for high-traffic apps:
      $server = SocketHttpServer::createForDirectAccess($logger, [
          'max_connections' => 5000,
          'max_requests' => 10000,
      ]);
      

Extension Points

  1. Custom Error Pages:

    $errorHandler = new class implements ErrorHandler {
        public function handleError(int $status, ?string $reason, ?Request $request): Response {
            return new Response(
                status: $status,
                body: "<h1>Error $status</h1><p>$reason</p>"
            );
        }
    };
    
  2. Dynamic Port Binding:

    $port = getenv('PORT') ?: 8080;
    $server->expose("0.0.0.0:$port");
    
  3. TLS Configuration:

    use Amp\Socket\BindContext;
    
    $context = BindContext::withTls(
        __DIR__.'/cert.pem',
        __DIR__.'/key.pem'
    );
    $server->expose('0.0.0.0:443', $context);
    

Laravel-Specific Tips

  1. Service Provider Integration:

    use Amp\Http\Server\SocketHttpServer;
    use Illuminate\Support\ServiceProvider;
    
    class AmpHttpServerProvider extends ServiceProvider {
        public function register() {
            $this->app->singleton(SocketHttpServer::class, function () {
                return SocketHttpServer::createForDirectAccess(
                    $this->app->make(\Psr\Log\LoggerInterface::class)
                );
            });
        }
    }
    
  2. Middleware Adaptation:

    • Convert Laravel middleware to amphp/http-server middleware:
      $laravelMiddleware = new class implements Middleware {
          public function handleRequest(Request $request, RequestHandler $next): Response {
              $response = $next->handleRequest($request);
              // Modify response (e.g., add headers)
              $response->setHeader('X-Powered-By', 'AMPHP');
              return $response;
          }
      };
      
  3. Route Caching:

    • Pre-compile routes for zero-overhead dispatch:
      $router = new Router();
      $router->addRoute('GET', '/', new HomeHandler());
      // Cache compiled routes if using a router with this feature.
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope