Skip to content

Instantly share code, notes, and snippets.

@recca0120
Last active January 9, 2022 06:08
Show Gist options
  • Save recca0120/ef504b71fd80ca3b72a8ae1e1f235668 to your computer and use it in GitHub Desktop.
Save recca0120/ef504b71fd80ca3b72a8ae1e1f235668 to your computer and use it in GitHub Desktop.
Cloudflare.php
<?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;
}
}
<?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