Skip to content

Commit 6ee4db7

Browse files
committed
feat(docs/http-handler): add HTTP handler section with middleware, logging, and retries
- Introduced full HTTP handler documentation from scratch - Demonstrates flexible control, custom middleware, logging, and retry features - Includes examples for default and custom handlers
1 parent 56bc690 commit 6ee4db7

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed

src/Http/README.md

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
## HTTP Handlers and middleware
2+
3+
The HTTP handler allows you to flexibly control requests and responses with custom middleware for logging, retries, and other features.
4+
5+
Out of the box, The `\OpenAI\Laravel\Http\Handler` is ready to use and automatically dispatches [Laravel HTTP events](https://laravel.com/docs/12.x/http-client#events) such as `RequestSending`, `ResponseReceived`, and `ConnectionFailed`.
6+
7+
For more advanced use cases, you can create a custom handler to add `logging`, `retries` , `with headers`, request/response transformations, or any other [Guzzle middleware](https://docs.guzzlephp.org/en/stable/handlers-and-middleware.html#middleware), allowing you to fully tailor the behavior of your HTTP requests.
8+
9+
### Handler Configuration
10+
11+
Configure your handler in `config/openai.php`:
12+
13+
```php
14+
'http_handler' => \OpenAI\Laravel\Http\Handler::class,
15+
```
16+
17+
**Add Custom Handler**
18+
19+
Need custom logging, retries, or middleware? Create your own:
20+
21+
```php
22+
'http_handler' => \App\Http\Handlers\CustomHandler::class,
23+
```
24+
25+
Accepts: callable, class and service container resolvable class.
26+
27+
### HTTP Handler default features
28+
29+
The built-in `\OpenAI\Laravel\Http\Handler` provides:
30+
31+
- Laravel HTTP events (`RequestSending`, `ResponseReceived`, `ConnectionFailed`)
32+
- Custom handler can use the `handle(...)` method through the handler's `__invoke(...)`.
33+
- Add middleware and map failures through `Handler::mapFailure`
34+
- Control whether events are dispatched with `Handler::shouldEvent(true)`
35+
36+
Perfect for seamless integration with zero configuration.
37+
38+
### HTTP Custom handler
39+
40+
You can create a custom handler to interact with the HTTP client and implement custom logic.
41+
42+
```php
43+
class CustomHandler
44+
{
45+
/**
46+
* Invoke the handler stack with the given request and options.
47+
*/
48+
public function __invoke($request, array $config)
49+
{
50+
$handler = \GuzzleHttp\HandlerStack::create();
51+
52+
// Add custom logic here: logging, retries, modifying requests, etc.
53+
54+
return $handler($request, $config);
55+
}
56+
}
57+
```
58+
59+
**Creating the handler by extending the `Handler` Class**
60+
61+
Extending the Handler class allow to create handler with `handle(...)`, including a `HandlerStack` instance. Additionally, it dispatches Laravel HTTP events and handles failures, logging, and more through middleware.
62+
63+
```php
64+
use OpenAI\Laravel\Http\Handler;
65+
66+
class CustomHandler extends Handler
67+
{
68+
/**
69+
* Invoke the handler stack with the given request and options.
70+
*/
71+
public function handle($handler, $request, array $config)
72+
{
73+
// Add custom logic here: logging, retries, modifying requests, etc.
74+
75+
return $handler($request, $config);
76+
}
77+
}
78+
```
79+
### HTTP Handler with guzzle middleware
80+
81+
This example demonstrates how to interact with the HTTP client using Guzzle middleware. You can create your own custom [middleware](https://docs.guzzlephp.org/en/stable/handlers-and-middleware.html#middleware) or continue using available [Guzzle middleware](https://github.com/guzzle/guzzle/blob/7.10/src/Middleware.php) like `tap`, `mapRequest`, `mapResponse`, `retry`, etc.
82+
83+
The middleware can be added to the handler stack using $handler->push, whether you’re using the __invoke method or hanlde(...) method by extending core handler.
84+
85+
```php
86+
use GuzzleHttp\Middleware;
87+
use Psr\Http\Message\RequestInterface;
88+
use Psr\Http\Message\ResponseInterface;
89+
90+
class CustomHandler
91+
{
92+
/**
93+
* Invoke the handler.
94+
*/
95+
public function __invoke($request, array $config)
96+
{
97+
$handler = \GuzzleHttp\HandlerStack::create();
98+
99+
// Example: modify request URI in mapRequest middleware
100+
$handler->push(Middleware::mapRequest(function (RequestInterface $request) {
101+
return $request->withUri(\GuzzleHttp\Psr7\Utils::uriFor('new-path'));
102+
}));
103+
104+
// Example: modify response body in mapResponse middleware
105+
$handler->push(Middleware::mapResponse(function (ResponseInterface $response) {
106+
return $response->withBody(\GuzzleHttp\Psr7\Utils::streamFor('Hello'));
107+
}));
108+
109+
return $handler($request, $config);
110+
}
111+
}
112+
```
113+
114+
**Adding Custom Headers to Requests**
115+
116+
Here’s an example of adding a custom header to the request using middleware. This example extends Laravel's Handler class to handle the request and apply the custom header:
117+
118+
```php
119+
use GuzzleHttp\Middleware;
120+
use OpenAI\Laravel\Http\Handler;
121+
122+
class CustomHeaderHandler extends Handler
123+
{
124+
/**
125+
* Invoke the handler.
126+
*/
127+
public function handle($handler, $request, array $config)
128+
{
129+
// Example: modify request URI in mapRequest middleware
130+
$handler->push(Middleware::mapRequest(function ($request) {
131+
return $request->withHeader('X-Custom-Name', 'Laravel');
132+
}));
133+
134+
return $handler($request, $config);
135+
}
136+
}
137+
```
138+
139+
#### HTTP Handler add retry middleware with guzzle
140+
141+
You can add retry http client request by creating a custom handler that pushes a [guzzle retry middleware](https://github.com/guzzle/guzzle/blob/7.10/src/Middleware.php#L179) onto the handler stack.
142+
143+
This example middleware will automatically retry requests in case of server errors (5xx responses) or other conditions you define.
144+
145+
```php
146+
use GuzzleHttp\Middleware;
147+
use OpenAI\Laravel\Http\Handler;
148+
149+
class RetryHandler extends Handler
150+
{
151+
/**
152+
* Invoke the handler.
153+
*/
154+
public function handle(\GuzzleHttp\HandlerStack $handler, $request, array $config)
155+
{
156+
// Example: add retry middleware
157+
$handler->push(Middleware::retry(function ($retries, $request, $response = null, $exception = null) {
158+
159+
// For instance, 3-retry for 5xx responses
160+
if ($retries < 3 && $response && $response->getStatusCode() >= 500) {
161+
return true; // Retry on server errors
162+
}
163+
164+
return false; // Don't retry if the conditions above are not met
165+
}));
166+
167+
return $handler($request, $config);
168+
169+
}
170+
}
171+
```
172+
173+
### HTTP Handler usage with client factory
174+
175+
You can configure the OpenAI client to use a HTTP client handler when creating the client via the factory
176+
177+
```php
178+
use OpenAI\Laravel\Facades\OpenAI;
179+
use OpenAI\Laravel\Http\Handler;
180+
181+
$client = OpenAI::factory()
182+
// Other configuration...
183+
->withHttpClient(new \GuzzleHttp\Client([
184+
'handler' => Handler::resolve(config('openai.http_handler')),
185+
]));
186+
```

0 commit comments

Comments
 (0)