Last active
January 9, 2022 06:08
-
-
Save recca0120/ef504b71fd80ca3b72a8ae1e1f235668 to your computer and use it in GitHub Desktop.
Cloudflare.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Middleware; | |
use Closure; | |
use Illuminate\Http\Request; | |
use Illuminate\Routing\UrlGenerator; | |
use Illuminate\Http\RedirectResponse; | |
class Cloudflare | |
{ | |
private $generator; | |
public function __construct(UrlGenerator $generator) | |
{ | |
$this->generator = $generator; | |
} | |
/** | |
* Handle an incoming request. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Closure $next | |
* @return mixed | |
*/ | |
public function handle($request, Closure $next) | |
{ | |
$scheme = $this->clientIp($request)->scheme($request); | |
if (is_null($scheme) === false && $scheme !== 'https') { | |
return new RedirectResponse($this->generator->to($request->getRequestUri(), [], true)); | |
} | |
return $next($request); | |
} | |
private function clientIp(Request $request) | |
{ | |
foreach (['HTTP_CF-Connecting-IP', 'HTTP_X-Forwarded-For'] as $key) { | |
$clientIp = $request->server($key); | |
if (is_null($clientIp) === false) { | |
$request->server->set('REMOTE_ADDR', $clientIp); | |
return $this; | |
} | |
} | |
return $this; | |
} | |
private function scheme(Request $request) | |
{ | |
$scheme = $this->getSchemeFromCfVisitor($request) ?: $request->server('HTTP_X_FORWARDED_PROTO'); | |
return is_null($scheme) === false ? $this->forceHttps($scheme) : null; | |
} | |
private function getSchemeFromCfVisitor($request) | |
{ | |
$cfVisitor = $request->server('HTTP_CF_VISITOR'); | |
if (is_null($cfVisitor) === false) { | |
$cfVisitorDecode = json_decode($cfVisitor); | |
return $cfVisitorDecode->scheme; | |
} | |
} | |
private function forceHttps($scheme) | |
{ | |
if ($scheme === 'https') { | |
$this->generator->forceScheme('https'); | |
} | |
return $scheme; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Mockery as m; | |
use Illuminate\Http\Request; | |
use PHPUnit\Framework\TestCase; | |
use App\Http\Middleware\Cloudflare; | |
use Illuminate\Routing\UrlGenerator; | |
class CloudflareTest extends TestCase | |
{ | |
protected function tearDown() | |
{ | |
parent::tearDown(); | |
m::close(); | |
} | |
/** @test */ | |
public function test_get_ip_from_HTTP_CF_CONNECTING_IP() | |
{ | |
$generator = m::mock(UrlGenerator::class); | |
$middleware = new Cloudflare($generator); | |
$cloudflare = [ | |
'HTTP_CF-Connecting-IP' => '1.2.3.4', | |
]; | |
$request = Request::create('/', 'GET', [], [], [], $cloudflare); | |
$next = function () { | |
}; | |
$middleware->handle($request, $next); | |
$this->assertSame($cloudflare['HTTP_CF-Connecting-IP'], $request->server('REMOTE_ADDR')); | |
} | |
/** @test */ | |
public function test_get_ip_from_HTTP_X_FORWARDED_FOR() | |
{ | |
$generator = m::mock(UrlGenerator::class); | |
$middleware = new Cloudflare($generator); | |
$cloudflare = [ | |
'HTTP_X-Forwarded-For' => '1.2.3.4', | |
]; | |
$request = Request::create('/', 'GET', [], [], [], $cloudflare); | |
$next = function () { | |
}; | |
$middleware->handle($request, $next); | |
$this->assertSame($cloudflare['HTTP_X-Forwarded-For'], $request->server('REMOTE_ADDR')); | |
} | |
/** @test */ | |
public function test_get_scheme_from_HTTP_CF_VISITOR() | |
{ | |
$generator = m::mock(UrlGenerator::class); | |
$middleware = new Cloudflare($generator); | |
$cloudflare = [ | |
'HTTP_CF_VISITOR' => '{"scheme":"https"}', | |
]; | |
$request = Request::create('/', 'GET', [], [], [], $cloudflare); | |
$next = function () { | |
}; | |
$generator->shouldReceive('forceScheme')->once()->with(m::on(function ($scheme) { | |
$this->assertSame('https', $scheme); | |
return true; | |
})); | |
$middleware->handle($request, $next); | |
} | |
/** @test */ | |
public function test_get_scheme_from_HTTP_X_FORWARDED_PROTO() | |
{ | |
$generator = m::mock(UrlGenerator::class); | |
$middleware = new Cloudflare($generator); | |
$cloudflare = [ | |
'HTTP_X_FORWARDED_PROTO' => 'https', | |
]; | |
$request = Request::create('/', 'GET', [], [], [], $cloudflare); | |
$next = function () { | |
}; | |
$generator->shouldReceive('forceScheme')->once()->with(m::on(function ($scheme) { | |
$this->assertSame('https', $scheme); | |
return true; | |
})); | |
$middleware->handle($request, $next); | |
} | |
/** @test */ | |
public function test_get_scheme_from_redirect_to_https() | |
{ | |
$generator = m::mock(UrlGenerator::class); | |
$middleware = new Cloudflare($generator); | |
$cloudflare = [ | |
'HTTP_CF_VISITOR' => '{"scheme":"http"}', | |
]; | |
$request = Request::create('/', 'GET', [], [], [], $cloudflare); | |
$next = function () { | |
}; | |
$generator->shouldReceive('to')->once()->with('/', [], true)->andReturn('https://localhost/'); | |
$response = $middleware->handle($request, $next); | |
$this->assertSame('https://localhost/', $response->getTargetUrl()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment