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

Commit 7a1f535

Browse files
committed
Merge branch 'hotfix/cached-iana-test-codes' into develop
Forward port #367
2 parents af7da80 + aaf7c43 commit 7a1f535

File tree

7 files changed

+90
-31
lines changed

7 files changed

+90
-31
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
doc/html/
33
vendor/
44
zf-mkdoc-theme/
5+
/test/TestAsset/.cache/
56
phpunit.xml

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ language: php
33
cache:
44
directories:
55
- $HOME/.composer/cache
6+
- test/TestAsset/.cache # Cache archives are currently set to expire after 28 days by default
67

78
env:
89
global:

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"psr/http-message": "^1.0"
3232
},
3333
"require-dev": {
34+
"ext-curl": "*",
3435
"ext-dom": "*",
3536
"ext-libxml": "*",
3637
"http-interop/http-factory-tests": "^0.5.0",

composer.lock

Lines changed: 10 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpunit.xml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
</filter>
1616

1717
<php>
18+
<env name="ALWAYS_REFRESH_IANA_HTTP_STATUS_CODES" value="false"/>
1819
<const name="REQUEST_FACTORY" value="Zend\Diactoros\RequestFactory"/>
1920
<const name="RESPONSE_FACTORY" value="Zend\Diactoros\ResponseFactory"/>
2021
<const name="SERVER_REQUEST_FACTORY" value="Zend\Diactoros\ServerRequestFactory"/>

test/ResponseTest.php

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
33
* @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4-
* @copyright Copyright (c) 2015-2018 Zend Technologies USA Inc. (http://www.zend.com)
4+
* @copyright Copyright (c) 2015-2019 Zend Technologies USA Inc. (http://www.zend.com)
55
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
66
*/
77

@@ -16,10 +16,24 @@
1616
use Zend\Diactoros\Response;
1717
use Zend\Diactoros\Stream;
1818

19+
use function curl_close;
20+
use function curl_exec;
21+
use function curl_getinfo;
22+
use function curl_init;
23+
use function curl_setopt;
24+
use function file_exists;
25+
use function file_put_contents;
26+
use function gmdate;
1927
use function in_array;
20-
use function libxml_set_streams_context;
2128
use function preg_match;
22-
use function stream_context_create;
29+
use function sprintf;
30+
use function strtotime;
31+
32+
use const CURLINFO_HTTP_CODE;
33+
use const CURLOPT_HTTPHEADER;
34+
use const CURLOPT_RETURNTRANSFER;
35+
use const CURLOPT_TIMEOUT;
36+
use const LOCK_EX;
2337

2438
class ResponseTest extends TestCase
2539
{
@@ -51,28 +65,68 @@ public function testReasonPhraseDefaultsToStandards()
5165
$this->assertSame('Unprocessable Entity', $response->getReasonPhrase());
5266
}
5367

54-
public function ianaCodesReasonPhrasesProvider()
68+
private function fetchIanaStatusCodes() : DOMDocument
5569
{
56-
$ianaHttpStatusCodes = new DOMDocument();
57-
58-
libxml_set_streams_context(
59-
stream_context_create(
60-
[
61-
'http' => [
62-
'method' => 'GET',
63-
'timeout' => 30,
64-
'user_agent' => 'PHP',
65-
],
66-
]
67-
)
68-
);
69-
70-
$ianaHttpStatusCodes->load('https://www.iana.org/assignments/http-status-codes/http-status-codes.xml');
71-
72-
if (! $ianaHttpStatusCodes->relaxNGValidate(__DIR__ . '/TestAsset/http-status-codes.rng')) {
73-
self::fail('Unable to retrieve IANA response status codes due to timeout or invalid XML');
70+
$updated = null;
71+
$ianaHttpStatusCodesFile = __DIR__ . '/TestAsset/.cache/http-status-codes.xml';
72+
$ianaHttpStatusCodes = null;
73+
if (file_exists($ianaHttpStatusCodesFile)) {
74+
$ianaHttpStatusCodes = new DOMDocument();
75+
$ianaHttpStatusCodes->load($ianaHttpStatusCodesFile);
76+
if (! $ianaHttpStatusCodes->relaxNGValidate(__DIR__ . '/TestAsset/http-status-codes.rng')) {
77+
$ianaHttpStatusCodes = null;
78+
}
79+
}
80+
if ($ianaHttpStatusCodes) {
81+
if (! getenv('ALWAYS_REFRESH_IANA_HTTP_STATUS_CODES')) {
82+
// use cached codes
83+
return $ianaHttpStatusCodes;
84+
}
85+
$xpath = new DOMXPath($ianaHttpStatusCodes);
86+
$xpath->registerNamespace('ns', 'http://www.iana.org/assignments');
87+
$updated = $xpath->query('//ns:updated')->item(0)->nodeValue;
88+
$updated = strtotime($updated);
89+
}
90+
91+
$ch = curl_init('https://www.iana.org/assignments/http-status-codes/http-status-codes.xml');
92+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
93+
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
94+
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP Curl');
95+
if ($updated) {
96+
$ifModifiedSince = sprintf(
97+
'If-Modified-Since: %s',
98+
gmdate('D, d M Y H:i:s \G\M\T', $updated)
99+
);
100+
curl_setopt($ch, CURLOPT_HTTPHEADER, [$ifModifiedSince]);
101+
}
102+
$response = curl_exec($ch);
103+
$responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
104+
curl_close($ch);
105+
106+
if ($responseCode === 304 && $ianaHttpStatusCodes) {
107+
// status codes did not change
108+
return $ianaHttpStatusCodes;
74109
}
75110

111+
if ($responseCode === 200) {
112+
$downloadedIanaHttpStatusCodes = new DOMDocument();
113+
$downloadedIanaHttpStatusCodes->loadXML($response);
114+
if ($downloadedIanaHttpStatusCodes->relaxNGValidate(__DIR__ . '/TestAsset/http-status-codes.rng')) {
115+
file_put_contents($ianaHttpStatusCodesFile, $response, LOCK_EX);
116+
return $downloadedIanaHttpStatusCodes;
117+
}
118+
}
119+
if ($ianaHttpStatusCodes) {
120+
// return cached codes if available
121+
return $ianaHttpStatusCodes;
122+
}
123+
self::fail('Unable to retrieve IANA response status codes due to timeout or invalid XML');
124+
}
125+
126+
public function ianaCodesReasonPhrasesProvider()
127+
{
128+
$ianaHttpStatusCodes = $this->fetchIanaStatusCodes();
129+
76130
$ianaCodesReasonPhrases = [];
77131

78132
$xpath = new DOMXPath($ianaHttpStatusCodes);

test/TestAsset/.cache/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)