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

Ensure checks for HTTPS scheme are case insensitive #318

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ All notable changes to this project will be documented in this file, in reverse

### Fixed

- [#318](https://github.com/zendframework/zend-diactoros/pull/318) fixes the logic for discovering whether an HTTPS scheme is in play
to be case insensitive when comparing header and SAPI values, ensuring no
false negative lookups occur.

- [#314](https://github.com/zendframework/zend-diactoros/pull/314) modifies error handling around opening a file resource within
`Zend\Diactoros\Stream::setStream()` to no longer use the second argument to
`set_error_handler()`, and instead check the error type in the handler itself;
Expand Down
12 changes: 9 additions & 3 deletions src/functions/marshal_uri_from_sapi.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,15 @@ function marshalUriFromSapi(array $server, array $headers)

// URI scheme
$scheme = 'http';
$https = array_key_exists('HTTPS', $server) ? $server['HTTPS'] : false;
if (($https && 'off' !== $https)
|| $getHeaderFromArray('x-forwarded-proto', $headers, false) === 'https'
if (array_key_exists('HTTPS', $server)) {
$https = $server['HTTPS'];
} elseif (array_key_exists('https', $server)) {
$https = $server['https'];
} else {
$https = false;
}
if (($https && 'off' !== strtolower($https))
|| strtolower($getHeaderFromArray('x-forwarded-proto', $headers, false)) === 'https'
) {
$scheme = 'https';
}
Expand Down
51 changes: 45 additions & 6 deletions test/ServerRequestFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,29 @@ public function testMarshalHostAndPortWillDetectPortInIpv6StyleHost()
$this->assertNull($uri->getPort());
}

public function testMarshalUriDetectsHttpsSchemeFromServerValue()
/**
* @return array
*/
public function httpsParamProvider()
{
return [
'lowercase' => ['https'],
'uppercase' => ['HTTPS'],
];
}

/**
* @dataProvider httpsParamProvider
* @param string $param
*/
public function testMarshalUriDetectsHttpsSchemeFromServerValue($param)
{
$request = new ServerRequest();
$request = $request->withUri(new Uri('http://example.com/'));
$request = $request->withHeader('Host', 'example.com');

$server = [
'HTTPS' => true,
$param => true,
];

$uri = marshalUriFromSapi($server, $request->getHeaders());
Expand All @@ -322,14 +337,34 @@ public function testMarshalUriDetectsHttpsSchemeFromServerValue()
$this->assertSame('https', $uri->getScheme());
}

public function testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff()
/**
* @return iterable
*/
public function httpsDisableParamProvider()
{
foreach ($this->httpsParamProvider() as $key => $data) {
$param = array_shift($data);
foreach (['lowercase-off', 'uppercase-off'] as $type) {
$key = sprintf('%s-%s', $key, $type);
$value = false !== strpos($type, 'lowercase') ? 'off' : 'OFF';
yield $key => [$param, $value];
}
}
}

/**
* @dataProvider httpsDisableParamProvider
* @param string $param
* @param string $value
*/
public function testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff($param, $value)
{
$request = new ServerRequest();
$request = $request->withUri(new Uri('http://example.com/'));
$request = $request->withHeader('Host', 'example.com');

$server = [
'HTTPS' => 'off',
$param => $value,
];

$uri = marshalUriFromSapi($server, $request->getHeaders());
Expand All @@ -338,12 +373,16 @@ public function testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff()
$this->assertSame('http', $uri->getScheme());
}

public function testMarshalUriDetectsHttpsSchemeFromXForwardedProtoValue()
/**
* @dataProvider httpsParamProvider
* @param string $xForwardedProto
*/
public function testMarshalUriDetectsHttpsSchemeFromXForwardedProtoValue($xForwardedProto)
{
$request = new ServerRequest();
$request = $request->withUri(new Uri('http://example.com/'));
$request = $request->withHeader('Host', 'example.com');
$request = $request->withHeader('X-Forwarded-Proto', 'https');
$request = $request->withHeader('X-Forwarded-Proto', $xForwardedProto);

$server = [];

Expand Down