Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Commit 4413d72

Browse files
committed
Merge branch 'hotfix/131-follow-100-continue' into develop
Forward port #131
2 parents 78571fa + 146f4d3 commit 4413d72

File tree

4 files changed

+60
-11
lines changed

4 files changed

+60
-11
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ All notable changes to this project will be documented in this file, in reverse
4040

4141
### Fixed
4242

43+
- introduces changes to `Response::fromString()` to pull the next line of the response
44+
and parse it for the status when a 100 status code is initially encountered, per https://tools.ietf.org/html/rfc7231\#section-6.2.1
45+
4346
- [#122](https://github.com/zendframework/zend-http/pull/122) fixes an issue with the stream response whereby if the `outputstream`
4447
option is set, the output file was opened twice; it is now opened exactly once.
4548

src/Response.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Zend\Http;
99

10+
use Zend\Http\Exception\RuntimeException;
1011
use Zend\Stdlib\ErrorHandler;
1112
use Zend\Stdlib\ResponseInterface;
1213

@@ -189,20 +190,18 @@ public static function fromString($string)
189190
$firstLine = array_shift($lines);
190191

191192
$response = new static();
193+
$response->parseStatusLine($firstLine);
192194

193-
$regex = '/^HTTP\/(?P<version>1\.[01]) (?P<status>\d{3})(?:[ ]+(?P<reason>.*))?$/';
194-
$matches = [];
195-
if (! preg_match($regex, $firstLine, $matches)) {
196-
throw new Exception\InvalidArgumentException(
197-
'A valid response status line was not found in the provided string'
198-
);
195+
/**
196+
* @link https://tools.ietf.org/html/rfc7231#section-6.2.1
197+
*/
198+
if ($response->statusCode === static::STATUS_CODE_100) {
199+
$next = array_shift($lines); // take next line
200+
$next = empty($next) ? array_shift($lines) : $next; // take next or skip if empty
201+
$response->parseStatusLine($next);
199202
}
200203

201-
$response->version = $matches['version'];
202-
$response->setStatusCode($matches['status']);
203-
$response->setReasonPhrase((isset($matches['reason']) ? $matches['reason'] : ''));
204-
205-
if (empty($lines)) {
204+
if (count($lines) === 0) {
206205
return $response;
207206
}
208207

@@ -243,6 +242,26 @@ public static function fromString($string)
243242
return $response;
244243
}
245244

245+
/**
246+
* @param string $line
247+
* @throws Exception\InvalidArgumentException
248+
* @throws Exception\RuntimeException
249+
*/
250+
protected function parseStatusLine($line)
251+
{
252+
$regex = '/^HTTP\/(?P<version>1\.[01]) (?P<status>\d{3})(?:[ ]+(?P<reason>.*))?$/';
253+
$matches = [];
254+
if (! preg_match($regex, $line, $matches)) {
255+
throw new Exception\InvalidArgumentException(
256+
'A valid response status line was not found in the provided string'
257+
);
258+
}
259+
260+
$this->version = $matches['version'];
261+
$this->setStatusCode($matches['status']);
262+
$this->setReasonPhrase((isset($matches['reason']) ? $matches['reason'] : ''));
263+
}
264+
246265
/**
247266
* @return Header\SetCookie[]
248267
*/

test/ResponseTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,16 @@ public function testPreventsCRLFAttackWhenDeserializing()
451451
);
452452
}
453453

454+
public function test100ContinueFromString()
455+
{
456+
$fixture = 'TOKEN=EC%XXXXXXXXXXXXX&TIMESTAMP=2017%2d10%2d10T09%3a02%3a55Z'
457+
."&CORRELATIONID=XXXXXXXXXX&ACK=Success&VERSION=65%2e1&BUILD=XXXXXXXXXX\r\n";
458+
459+
$request = Response::fromString($this->readResponse('response_100_continue'));
460+
$this->assertEquals(Response::STATUS_CODE_200, $request->getStatusCode());
461+
$this->assertEquals($fixture, $request->getBody());
462+
}
463+
454464
/**
455465
* Helper function: read test response from file
456466
*

test/_files/response_100_continue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
HTTP/1.1 100 Continue
2+
3+
HTTP/1.1 200 OK
4+
Date: Tue, 10 Oct 2017 09:02:53 GMT
5+
Server: Apache
6+
X-SLR-RETRY-API: SetExpressCheckout
7+
X-PAYPAL-OPERATION-NAME: SetExpressCheckout
8+
X-PAYPAL-API-RC:
9+
Connection: close
10+
HTTP_X_PP_AZ_LOCATOR: sandbox.slc
11+
Paypal-Debug-Id: e8abe44ddc3bd
12+
Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D1880%26app%3Dappdispatcher_apit%26TIME%3D3196902489%26HTTP_X_PP_AZ_LOCATOR%3Dsandbox.slc; Expires=Tue, 10 Oct 2017 09:32:55 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
13+
Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
14+
Content-Length: 137
15+
Content-Type: text/plain; charset=utf-8
16+
17+
TOKEN=EC%XXXXXXXXXXXXX&TIMESTAMP=2017%2d10%2d10T09%3a02%3a55Z&CORRELATIONID=XXXXXXXXXX&ACK=Success&VERSION=65%2e1&BUILD=XXXXXXXXXX

0 commit comments

Comments
 (0)