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 Adapter Laravel Package

widop/http-adapter

Widop HTTP Adapter provides a simple abstraction layer for making HTTP requests in PHP, letting you swap underlying clients (like cURL or other libraries) without changing your code. Useful for libraries and apps that need a lightweight, interchangeable HTTP client.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require widop/http-adapter
    

    Register the service provider in config/app.php:

    'providers' => [
        Widop\HttpAdapter\ServiceProvider::class,
    ],
    
  2. Basic Usage Inject the adapter via Laravel's dependency injection:

    use Widop\HttpAdapter\Facades\HttpAdapter;
    
    public function testRequest()
    {
        $response = HttpAdapter::get('https://api.example.com/data');
        return $response->getBody();
    }
    
  3. First Use Case: API Calls Replace Guzzle or Symfony HTTP client calls with this adapter for consistency:

    $response = HttpAdapter::post('https://api.example.com/users', [
        'json' => ['name' => 'John Doe'],
    ]);
    

Implementation Patterns

Dependency Injection

  • Service Binding: Prefer binding the adapter to interfaces for testability:

    $this->app->bind(
        Widop\HttpAdapter\Contracts\HttpAdapter::class,
        Widop\HttpAdapter\Adapter::class
    );
    
  • Facade vs. Injection: Use the HttpAdapter facade for quick scripts, but inject the adapter class in controllers/services for better testing.

Common Workflows

  1. Request Configuration Chain methods for fluent configuration:

    $response = HttpAdapter::create()
        ->withHeader('Authorization', 'Bearer token')
        ->withOption('timeout', 30)
        ->get('https://api.example.com/endpoint');
    
  2. Middleware Integration Attach middleware to the adapter for request/response processing:

    HttpAdapter::middleware([
        new \App\Http\Middleware\LogRequest(),
        new \App\Http\Middleware\RetryFailedRequests(),
    ]);
    
  3. Async Requests Use the async() method for non-blocking calls (if supported by the underlying client):

    $promise = HttpAdapter::async()->get('https://api.example.com/long-running-task');
    $promise->then(function ($response) { /* ... */ });
    
  4. Retry Logic Implement retry logic via middleware or the adapter’s built-in retry options:

    $response = HttpAdapter::withRetry(3, 100)->get('https://api.example.com/flaky-endpoint');
    

Laravel Integration

  • Service Provider: Extend the provider to add custom clients or configurations:

    public function register()
    {
        $this->app->singleton(Widop\HttpAdapter\Contracts\HttpAdapter::class, function ($app) {
            return (new Widop\HttpAdapter\Adapter())
                ->withBaseUri(config('services.api.base_uri'))
                ->withDefaultHeaders(config('services.api.headers'));
        });
    }
    
  • Config File: Define default configurations in config/http-adapter.php:

    return [
        'timeout' => 30,
        'base_uri' => env('API_BASE_URI'),
        'headers' => [
            'Accept' => 'application/json',
        ],
    ];
    

Gotchas and Tips

Pitfalls

  1. PHP 5.3+ Compatibility

    • Avoid modern PHP features (e.g., arrow functions, match expressions) in middleware or callbacks.
    • Use anonymous functions with create_function() if needed for legacy support.
  2. Middleware Execution Order

    • Middleware runs in registration order (LIFO). Test order-dependent logic:
      HttpAdapter::middleware([new A(), new B()]); // B runs first, A last
      
  3. Response Handling

    • The adapter returns a Widop\HttpAdapter\Response object. Use getBody(), getStatusCode(), or json() methods:
      $response = HttpAdapter::get('...');
      $data = $response->json(); // Throws exception on non-JSON responses
      
    • Always check getStatusCode() before parsing the body to avoid errors.
  4. Thread Safety

    • The adapter is not thread-safe by default. Use a singleton or manage instances carefully in concurrent environments (e.g., queues).

Debugging

  • Enable Verbose Logging Add a middleware to log requests/responses:

    HttpAdapter::middleware(new class {
        public function handle($request, $next) {
            \Log::debug('Request:', $request->toArray());
            $response = $next($request);
            \Log::debug('Response:', $response->getBody());
            return $response;
        }
    });
    
  • Check Underlying Client The adapter wraps a low-level HTTP client (e.g., curl, stream). Debug issues by inspecting the raw client configuration:

    $adapter = HttpAdapter::getAdapter(); // Access the underlying client
    

Extension Points

  1. Custom Clients Implement Widop\HttpAdapter\Contracts\HttpClient to integrate alternative HTTP libraries (e.g., ReactPHP):

    class CustomClient implements HttpClient {
        public function send(Request $request) { /* ... */ }
    }
    
  2. Response Decorators Extend the Response class to add domain-specific methods:

    class ApiResponse extends Widop\HttpAdapter\Response {
        public function getUserData() {
            return $this->json()['data'];
        }
    }
    

    Bind it in the service provider:

    $this->app->bind(
        Widop\HttpAdapter\Response::class,
        App\Http\ApiResponse::class
    );
    
  3. Request Factories Create a factory class to standardize request creation:

    class ApiRequestFactory {
        public static function users() {
            return HttpAdapter::create()
                ->withBasePath('/users')
                ->withHeader('X-API-Key', config('api.key'));
        }
    }
    

Configuration Quirks

  • Base URI Handling The adapter does not automatically append a trailing slash to base_uri. Ensure consistency:

    // Correct:
    HttpAdapter::withBaseUri('https://api.example.com/')->get('users');
    // Incorrect (may cause 404):
    HttpAdapter::withBaseUri('https://api.example.com')->get('users');
    
  • Default Headers Headers set via withDefaultHeaders() cannot be overridden per-request. Use withHeader() for request-specific overrides:

    HttpAdapter::withDefaultHeaders(['User-Agent' => 'MyApp/1.0'])
        ->withHeader('X-Custom', 'override') // Overrides only for this request
        ->get('...');
    
  • SSL Verification Disable SSL verification only in development (never in production):

    HttpAdapter::withOption('verify_peer', false); // Use at your own risk!
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky