Skip to content

Commit 70d8834

Browse files
committed
update readme
1 parent 3508476 commit 70d8834

File tree

4 files changed

+67
-17
lines changed

4 files changed

+67
-17
lines changed

README.md

+30-4
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ implementations for [PSR-17 (HTTP Factories)](https://www.php-fig.org/psr/psr-17
2121
$client = new \Aternos\CurlPsr\Psr18\Client();
2222
```
2323

24-
When creating a client, you can optionally provide a PSR-17 `ResponseFactoryInterface` instance. By default,
25-
the client will use the `Aternos\CurlPsr\Psr17\Psr17Factory` class included in this library.
24+
When creating a client, you can optionally provide PSR-17 `ResponseFactoryInterface` and `UriFactoryInterface` instances.
25+
By default, the client will use the `Aternos\CurlPsr\Psr17\Psr17Factory` class included in this library.
2626

27-
Additionally, you can pass an optional `CurlHandleFactoryInterface` instance as the second argument,
28-
which is mainly used for testing purposes.
27+
Additionally, you can pass an optional `UriResolverInterface` instance, which is used to resolve redirect targets.
2928

3029
### Configuring the client
3130

@@ -52,7 +51,34 @@ $client->setProgressCallback(function (
5251
});
5352
```
5453

54+
#### Custom cURL options
55+
56+
You can set custom cURL options using the `setCurlOption` method. Note that some options cannot be set, since they are
57+
used internally by the client.
58+
59+
#### Redirects
60+
61+
The client will follow redirects by default. You can set the maximum number of redirects to follow using the
62+
`setMaxRedirects` method. It is also possible to disable redirects using `setFollowRedirects`. The difference between
63+
setting the maximum number of redirects to 0 and disabling redirects is that the former will throw an exception if a
64+
redirect is received, while the latter will simply return the redirect response.
65+
66+
Only when status `303 See Other` is received, the client will automatically change the request method to `GET` and
67+
remove the request body. Historically, this behavior was also sometimes present for `301` and `302`, so it is possible
68+
to enable it for other status codes using the `setRedirectToGetStatusCodes` method.
69+
70+
Status `300 Multiple Choices` will only be treated as a redirect if the `Location` header is present.
71+
Otherwise, the response will be returned as is.
72+
73+
To manage how redirect targets are resolved, or limit what locations the client can be redirected to,
74+
you can pass an instance of `UriResolverInterface` to the client constructor.
75+
76+
When a redirect response is received that does not prompt the client to change the request method to `GET`
77+
and the body stream cannot be rewound, an exception is thrown. This is because the client cannot resend the request
78+
with the same body stream.
79+
5580
#### Progress callback
81+
5682
The progress callback function works the same way as the `CURLOPT_PROGRESSFUNCTION` in cURL,
5783
except that it receives the PSR-7 request object instead of a cURL handle as the first argument.
5884
Please note that the request object passed to the callback is not necessarily same instance that was

src/Psr18/Client.php

+19-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ protected function doSendRequest(RequestInterface $request, ClientOptions $optio
226226

227227
$response = $headerParser->applyToResponse($response);
228228

229-
if ($this->isRedirect($response)) {
229+
if ($options->followRedirects && $this->isRedirect($response)) {
230230
if (!$fiber->isTerminated()) {
231231
try {
232232
$fiber->throw(new RequestRedirectedException());
@@ -553,4 +553,22 @@ public function getRedirectToGetStatusCodes(): array
553553
{
554554
return $this->options->redirectToGetStatusCodes;
555555
}
556+
557+
/**
558+
* @param bool $followRedirects
559+
* @return $this
560+
*/
561+
public function setFollowRedirects(bool $followRedirects): static
562+
{
563+
$this->options->followRedirects = $followRedirects;
564+
return $this;
565+
}
566+
567+
/**
568+
* @return bool
569+
*/
570+
public function getFollowRedirects(): bool
571+
{
572+
return $this->options->followRedirects;
573+
}
556574
}

src/Psr18/ClientOptions.php

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
class ClientOptions
88
{
99
public int $timeout = 0;
10+
public bool $followRedirects = true;
1011
public int $maxRedirects = 10;
1112
public string $cookieFile = "";
1213
public ?Closure $progressCallback = null;

tests/HttpClientTest.php

+17-12
Original file line numberDiff line numberDiff line change
@@ -345,18 +345,6 @@ public function testMaxRedirects(): void
345345
$this->assertFalse($this->curlHandle->getOption(CURLOPT_FOLLOWLOCATION));
346346
}
347347

348-
public function testDisableRedirects(): void
349-
{
350-
$this->client->setMaxRedirects(0);
351-
$this->assertEquals(0, $this->client->getMaxRedirects());
352-
353-
$request = $this->requestFactory->createRequest("GET", "https://example.com");
354-
$this->client->sendRequest($request);
355-
356-
$this->assertFalse($this->curlHandle->getOption(CURLOPT_FOLLOWLOCATION));
357-
$this->assertEquals(0, $this->curlHandle->getOption(CURLOPT_MAXREDIRS));
358-
}
359-
360348
public function testCookieFile(): void
361349
{
362350
$this->client->setCookieFile("cookie.txt");
@@ -445,6 +433,23 @@ public function testRedirect(): void
445433
$this->assertEquals("test1234", (string) $body2);
446434
}
447435

436+
public function testDisableRedirects(): void
437+
{
438+
$this->curlHandle->setInfo(["http_code" => 302])
439+
->setResponseHeaders([
440+
"Location: https://example.com/redirect"
441+
]);
442+
443+
$request = $this->requestFactory->createRequest("GET", "https://example.com");
444+
$this->client->setFollowRedirects(false);
445+
$this->assertEquals(false, $this->client->getFollowRedirects());
446+
447+
$response = $this->client->sendRequest($request);
448+
449+
$this->assertEquals(302, $response->getStatusCode());
450+
$this->assertEquals("https://example.com/redirect", $response->getHeaderLine("Location"));
451+
}
452+
448453
public function testThrowOnRedirectIfBodyIsNotSeekable(): void
449454
{
450455
$this->curlHandle->setInfo(["http_code" => 302])

0 commit comments

Comments
 (0)