Skip to content

Commit 0eb04ae

Browse files
committed
Merge branch 'request-body'
* request-body: cs readme update clean up undo debug debug test bring content-type debug debug exit after send() re-set client headers debug register chrome-extension via onBootstrap handle chrome extension like Postman skip https test call on php < 7 test keep request and metehod and re-call uri with httpsed scheme for non-empty request body
2 parents 4655289 + b3d9f2e commit 0eb04ae

3 files changed

Lines changed: 103 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Features
1818
- [x] enable/disable force https
1919
- [x] Force Https to All routes
2020
- [x] Force Https to specific routes only
21+
- [x] Keep header, request method, request body if http request has content (eg: on POST request method)
2122

2223
Installation
2324
------------

spec/Listener/ForceHttpsSpec.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
use ForceHttpsModule\Listener\ForceHttps;
66
use Kahlan\Plugin\Double;
7+
use Kahlan\Plugin\Quit;
8+
use Kahlan\QuitException;
79
use Zend\Console\Console;
810
use Zend\EventManager\EventManagerInterface;
11+
use Zend\Http\Client;
12+
use Zend\Http\Header\Origin;
13+
use Zend\Http\Headers;
914
use Zend\Http\PhpEnvironment\Request;
1015
use Zend\Http\PhpEnvironment\Response;
1116
use Zend\Mvc\MvcEvent;
@@ -133,6 +138,63 @@
133138

134139
});
135140

141+
it('keep request and method and re-call uri with httpsed scheme for non-empty request body', function () {
142+
143+
skipIf(PHP_MAJOR_VERSION < 7);
144+
Quit::disable();
145+
146+
Console::overrideIsConsole(false);
147+
$listener = new ForceHttps([
148+
'enable' => true,
149+
'force_all_routes' => true,
150+
'force_specific_routes' => [],
151+
]);
152+
153+
$mvcEvent = Double::instance(['extends' => MvcEvent::class, 'methods' => '__construct']);
154+
$response = Double::instance(['extends' => Response::class]);
155+
$request = Double::instance(['extends' => Request::class]);
156+
$uri = Double::instance(['extends' => Uri::class]);
157+
$client = Double::instance(['extends' => Client::class]);
158+
$clientResponse = Double::instance(['extends' => Response::class]);
159+
160+
allow($mvcEvent)->toReceive('getRequest')->andReturn($request);
161+
allow($request)->toReceive('getUri')->andReturn($uri);
162+
allow($uri)->toReceive('getScheme')->andReturn('http');
163+
allow($mvcEvent)->toReceive('getRouteMatch', 'getMatchedRouteName')->andReturn('api');
164+
allow($uri)->toReceive('setScheme')->with('https')->andReturn($uri);
165+
allow($uri)->toReceive('toString')->andReturn('https://example.com/api');
166+
allow($mvcEvent)->toReceive('getResponse')->andReturn($response);
167+
168+
$headers = new Headers();
169+
allow($headers)->toReceive('toArray')->andReturn([
170+
'Origin' => 'chrome-extension: //random',
171+
'Content-Type' => 'application/json',
172+
]);
173+
174+
allow($request)->toReceive('getContent')->andReturn('{"foo":"fooValue"}');
175+
allow($request)->toReceive('getMethod')->andReturn('POST');
176+
allow($request)->toReceive('getHeaders')->andReturn($headers);
177+
178+
allow($client)->toReceive('setUri')->with('https://example.com/about');
179+
allow($client)->toReceive('setMethod')->with('POST');
180+
allow($client)->toReceive('setRawBody')->with('{"foo":"fooValue"}');
181+
allow($client)->toReceive('setHeaders')->with($request->getHeaders());
182+
183+
allow($clientResponse)->toReceive('getBody')->andReturn('{}');
184+
allow($clientResponse)->toReceive('getStatusCode')->andReturn(200);
185+
allow($client)->toReceive('send')->andReturn($clientResponse);
186+
187+
allow($response)->toReceive('setStatusCode')->with(200)->andReturn($response);
188+
allow($response)->toReceive('send');
189+
190+
expect($mvcEvent)->toReceive('getResponse');
191+
$closure = function() use ($listener, $mvcEvent){
192+
$listener->forceHttpsScheme($mvcEvent);
193+
};
194+
expect($closure)->toThrow(new QuitException());
195+
196+
});
197+
136198
});
137199

138200
});

src/Listener/ForceHttps.php

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use Zend\Console\Console;
66
use Zend\EventManager\AbstractListenerAggregate;
77
use Zend\EventManager\EventManagerInterface;
8+
use Zend\Http\Client;
9+
use Zend\Http\Header\Origin;
810
use Zend\Mvc\MvcEvent;
911

1012
class ForceHttps extends AbstractListenerAggregate
@@ -43,7 +45,8 @@ public function attach(EventManagerInterface $events, $priority = 1)
4345
*/
4446
public function forceHttpsScheme(MvcEvent $e)
4547
{
46-
$uri = $e->getRequest()->getUri();
48+
$request = $e->getRequest();
49+
$uri = $request->getUri();
4750
$uriScheme = $uri->getScheme();
4851
if ($uriScheme === 'https') {
4952
return;
@@ -58,9 +61,43 @@ public function forceHttpsScheme(MvcEvent $e)
5861
return;
5962
}
6063

61-
$httpsRequestUri = $uri->setScheme('https')->toString();
64+
$response = $e->getResponse();
65+
$uriWithScheme = $uri->setScheme('https');
66+
$httpsRequestUri = $uriWithScheme->toString();
67+
68+
// if has request body, then
69+
// a.keep headers, request method, and body
70+
// b.call uri with https
71+
if (! empty($content = $request->getContent())) {
72+
73+
// keep methods and body
74+
$client = new Client();
75+
$client->setMethod($request->getMethod());
76+
$client->setRawBody($content);
77+
78+
// keep headers with clean up "Origin" and re-set headers
79+
$requestHeaders = $request->getHeaders();
80+
$headers = $requestHeaders->toArray();
81+
unset($headers['Origin']);
82+
$requestHeaders->clearHeaders();
83+
$requestHeaders->addHeaders($headers);
84+
$requestHeaders->addHeader(new Origin($uriScheme . '://' . $uri->getHost()));
85+
$client->setHeaders($requestHeaders);
86+
87+
// call uri with https
88+
$client->setUri($httpsRequestUri);
89+
$result = $client->send();
90+
91+
// send response
92+
$response->setContent($result->getBody());
93+
$response->setStatusCode($result->getStatusCode());
94+
$response->getHeaders()
95+
->addHeaderLine('Content-Type', $headers['Content-Type']);
96+
97+
$response->send();
98+
exit(0);
99+
}
62100

63-
$response = $e->getResponse();
64101
$response->setStatusCode(302);
65102
$response->getHeaders()
66103
->addHeaderLine('Location', $httpsRequestUri);

0 commit comments

Comments
 (0)