Skip to content

Commit fca7492

Browse files
authored
Merge pull request #33 from donatj/feature/changableDefault
Adds Changeable Default Response
2 parents db54c1d + fb0230b commit fca7492

File tree

9 files changed

+292
-48
lines changed

9 files changed

+292
-48
lines changed

README.md

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Latest Stable Version](https://poser.pugx.org/donatj/mock-webserver/version)](https://packagist.org/packages/donatj/mock-webserver)
44
[![License](https://poser.pugx.org/donatj/mock-webserver/license)](https://packagist.org/packages/donatj/mock-webserver)
55
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/donatj/mock-webserver/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/donatj/mock-webserver)
6-
[![Build Status](https://github.com/donatj/mock-webserver/workflows/CI/badge.svg?)](https://github.com/donatj/mock-webserver/actions?query=workflow%3ACI)
6+
[![CI](https://github.com/donatj/mock-webserver/workflows/CI/badge.svg?)](https://github.com/donatj/mock-webserver/actions?query=workflow%3ACI)
77
[![Build Status](https://travis-ci.org/donatj/mock-webserver.svg?branch=master)](https://travis-ci.org/donatj/mock-webserver)
88

99

@@ -101,7 +101,7 @@ require __DIR__ . '/../vendor/autoload.php';
101101
$server = new MockWebServer;
102102
$server->start();
103103

104-
// We define the servers response to requests of the /definedPath endpoint
104+
// We define the server's response to requests of the /definedPath endpoint
105105
$url = $server->setResponseOfPath(
106106
'/definedPath',
107107
new Response(
@@ -137,6 +137,53 @@ Content-type: text/html; charset=UTF-8
137137
This is our http body response
138138
```
139139

140+
### Change Default Response
141+
142+
```php
143+
<?php
144+
145+
use donatj\MockWebServer\MockWebServer;
146+
use donatj\MockWebServer\Responses\NotFoundResponse;
147+
148+
require __DIR__ . '/../vendor/autoload.php';
149+
150+
$server = new MockWebServer;
151+
$server->start();
152+
153+
// The default response is donatj\MockWebServer\Responses\DefaultResponse
154+
// which returns an HTTP 200 and a descriptive JSON payload.
155+
//
156+
// Change the default response to donatj\MockWebServer\Responses\NotFoundResponse
157+
// to get a standard 404.
158+
//
159+
// Any other response may be specified as default as well.
160+
$server->setDefaultResponse(new NotFoundResponse);
161+
162+
$content = file_get_contents($server->getServerRoot() . '/PageDoesNotExist', false, stream_context_create([
163+
'http' => [ 'ignore_errors' => true ] // allow reading 404s
164+
]));
165+
166+
// $http_response_header is a little known variable magically defined
167+
// in the current scope by file_get_contents with the response headers
168+
echo implode("\n", $http_response_header) . "\n\n";
169+
echo $content . "\n";
170+
171+
```
172+
173+
Outputs:
174+
175+
```
176+
HTTP/1.0 404 Not Found
177+
Host: 127.0.0.1:61355
178+
Date: Mon, 30 Aug 2021 20:02:58 GMT
179+
Connection: close
180+
X-Powered-By: PHP/7.3.29
181+
Content-type: text/html; charset=UTF-8
182+
183+
VND.DonatStudios.MockWebServer: Resource '/PageDoesNotExist' not found!
184+
185+
```
186+
140187
### PHPUnit
141188

142189
```php

docs/docs.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,24 @@ Set a specified path to provide a specific response
115115

116116
---
117117

118+
### Method: MockWebServer->setDefaultResponse
119+
120+
```php
121+
function setDefaultResponse(\donatj\MockWebServer\ResponseInterface $response)
122+
```
123+
124+
Override the default server response, e.g. Fallback or 404
125+
126+
#### Parameters:
127+
128+
- ***\donatj\MockWebServer\ResponseInterface*** `$response`
129+
130+
#### Returns:
131+
132+
- ***void***
133+
134+
---
135+
118136
### Method: MockWebServer->getLastRequest
119137

120138
```php
@@ -273,4 +291,16 @@ Set the Response for the Given Method
273291
#### Parameters:
274292

275293
- ***string*** `$method`
276-
- ***\donatj\MockWebServer\ResponseInterface*** `$response`
294+
- ***\donatj\MockWebServer\ResponseInterface*** `$response`
295+
296+
## Built-In Responses
297+
298+
### Class: \donatj\MockWebServer\Responses\DefaultResponse
299+
300+
The Built-In Default Response.
301+
302+
Results in an HTTP 200 with a JSON encoded version of the incoming Request
303+
304+
### Class: \donatj\MockWebServer\Responses\NotFoundResponse
305+
306+
Basic Built-In 404 Response

example/simple.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
$server = new MockWebServer;
99
$server->start();
1010

11-
// We define the servers response to requests of the /definedPath endpoint
11+
// We define the server's response to requests of the /definedPath endpoint
1212
$url = $server->setResponseOfPath(
1313
'/definedPath',
1414
new Response(

mddoc.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ I would be happy to accept pull requests that correct this.
2828
<file name="src/Response.php"/>
2929
<file name="src/ResponseStack.php"/>
3030
<file name="src/ResponseByMethod.php"/>
31+
<section title="Built-In Responses">
32+
<file name="src/Responses/DefaultResponse.php"/>
33+
<file name="src/Responses/NotFoundResponse.php"/>
34+
</section>
3135
</section>
3236
</docpage>
3337
</section>
@@ -49,6 +53,11 @@ I would be happy to accept pull requests that correct this.
4953
<text>Outputs:</text>
5054
<exec cmd="php example/simple.php" format="code-block" />
5155
</section>
56+
<section title="Change Default Response">
57+
<source name="example/notfound.php" lang="php"/>
58+
<text>Outputs:</text>
59+
<exec cmd="php example/notfound.php" format="code-block" />
60+
</section>
5261
<section title="PHPUnit">
5362
<source name="example/phpunit.php" lang="php"/>
5463
</section>

src/InternalServer.php

Lines changed: 86 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace donatj\MockWebServer;
44

55
use donatj\MockWebServer\Exceptions\ServerException;
6+
use donatj\MockWebServer\Responses\DefaultResponse;
7+
use donatj\MockWebServer\Responses\NotFoundResponse;
68

79
/**
810
* Class InternalServer
@@ -24,6 +26,8 @@ class InternalServer {
2426
*/
2527
private $header;
2628

29+
const DEFAULT_REF = 'default';
30+
2731
/**
2832
* InternalServer constructor.
2933
*
@@ -82,83 +86,121 @@ public static function aliasPath( $tmpPath, $path ) {
8286
);
8387
}
8488

89+
/**
90+
* @param string $ref
91+
* @return ResponseInterface|null
92+
*/
93+
private function responseForRef( $ref ) {
94+
$path = $this->tmpPath . DIRECTORY_SEPARATOR . $ref;
95+
if( !is_readable($path) ) {
96+
return null;
97+
}
98+
99+
$content = file_get_contents($path);
100+
$response = unserialize($content);
101+
if( !$response instanceof ResponseInterface ) {
102+
throw new ServerException('invalid serialized response');
103+
}
104+
105+
return $response;
106+
}
107+
85108
public function __invoke() {
86-
$path = $this->getDataPath();
87-
88-
if( $path !== false ) {
89-
if( is_readable($path) ) {
90-
$content = file_get_contents($path);
91-
$response = unserialize($content);
92-
if( !$response instanceof ResponseInterface ) {
93-
throw new ServerException('invalid serialized response');
94-
}
95-
96-
http_response_code($response->getStatus($this->request));
97-
98-
foreach( $response->getHeaders($this->request) as $key => $header ) {
99-
if( is_int($key) ) {
100-
call_user_func($this->header, $header);
101-
} else {
102-
call_user_func($this->header, "{$key}: {$header}");
103-
}
104-
}
105-
$body = $response->getBody($this->request);
106-
107-
if( $response instanceof MultiResponseInterface ) {
108-
$response->next();
109-
self::storeResponse($this->tmpPath, $response);
110-
}
111-
112-
echo $body;
109+
$ref = $this->getRefForUri($this->request->getParsedUri()['path']);
110+
111+
if( $ref !== null ) {
112+
$response = $this->responseForRef($ref);
113+
if( $response ) {
114+
$this->sendResponse($response);
113115

114116
return;
115117
}
116118

117-
http_response_code(404);
118-
echo MockWebServer::VND . ": Resource '{$path}' not found!\n";
119+
$this->sendResponse(new NotFoundResponse);
119120

120121
return;
121122
}
122123

123-
header('Content-Type: application/json');
124+
$response = $this->responseForRef(self::DEFAULT_REF);
125+
if( $response ) {
126+
$this->sendResponse($response);
124127

125-
echo json_encode($this->request, JSON_PRETTY_PRINT);
128+
return;
129+
}
130+
131+
$this->sendResponse(new DefaultResponse);
132+
}
133+
134+
protected function sendResponse( ResponseInterface $response ) {
135+
http_response_code($response->getStatus($this->request));
136+
137+
foreach( $response->getHeaders($this->request) as $key => $header ) {
138+
if( is_int($key) ) {
139+
call_user_func($this->header, $header);
140+
} else {
141+
call_user_func($this->header, "{$key}: {$header}");
142+
}
143+
}
144+
145+
echo $response->getBody($this->request);
146+
147+
if( $response instanceof MultiResponseInterface ) {
148+
$response->next();
149+
self::storeResponse($this->tmpPath, $response);
150+
}
126151
}
127152

128153
/**
129-
* @return false|string
154+
* @return string|null
130155
*/
131-
protected function getDataPath() {
132-
$path = false;
133-
134-
$uriPath = $this->request->getParsedUri()['path'];
156+
protected function getRefForUri( $uriPath ) {
135157
$aliasPath = self::aliasPath($this->tmpPath, $uriPath);
158+
136159
if( file_exists($aliasPath) ) {
137160
if( $path = file_get_contents($aliasPath) ) {
138-
$path = $this->tmpPath . DIRECTORY_SEPARATOR . $path;
161+
return $path;
139162
}
140-
} elseif( preg_match('%^/' . preg_quote(MockWebServer::VND) . '/([0-9a-fA-F]{32})$%', $uriPath, $matches) ) {
141-
$path = $this->tmpPath . DIRECTORY_SEPARATOR . $matches[1];
163+
} elseif( preg_match('%^/' . preg_quote(MockWebServer::VND, '%') . '/([0-9a-fA-F]{32})$%', $uriPath, $matches) ) {
164+
return $matches[1];
142165
}
143166

144-
return $path;
167+
return null;
145168
}
146169

147170
/**
148-
* @internal
149171
* @param string $tmpPath
150172
* @param \donatj\MockWebServer\ResponseInterface $response
151173
* @return string
174+
* @internal
152175
*/
153176
public static function storeResponse( $tmpPath, ResponseInterface $response ) {
154-
$ref = $response->getRef();
177+
$ref = $response->getRef();
178+
self::storeRef($response, $tmpPath, $ref);
179+
180+
return $ref;
181+
}
182+
183+
/**
184+
* @param string $tmpPath
185+
* @param \donatj\MockWebServer\ResponseInterface $response
186+
* @return void
187+
* @internal
188+
*/
189+
public static function storeDefaultResponse( $tmpPath, ResponseInterface $response ) {
190+
self::storeRef($response, $tmpPath, self::DEFAULT_REF);
191+
}
192+
193+
/**
194+
* @param \donatj\MockWebServer\ResponseInterface $response
195+
* @param string $tmpPath
196+
* @param string $ref
197+
*/
198+
private static function storeRef( ResponseInterface $response, $tmpPath, $ref ) {
155199
$content = serialize($response);
156200

157201
if( !file_put_contents($tmpPath . DIRECTORY_SEPARATOR . $ref, $content) ) {
158202
throw new Exceptions\RuntimeException('Failed to write temporary content');
159203
}
160-
161-
return $ref;
162204
}
163205

164206
}

src/MockWebServer.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,16 @@ public function setResponseOfPath( $path, ResponseInterface $response ) {
178178
return $this->getServerRoot() . $path;
179179
}
180180

181+
/**
182+
* Override the default server response, e.g. Fallback or 404
183+
*
184+
* @param \donatj\MockWebServer\ResponseInterface $response
185+
* @return void
186+
*/
187+
public function setDefaultResponse( ResponseInterface $response ) {
188+
InternalServer::storeDefaultResponse($this->tmpDir, $response);
189+
}
190+
181191
/**
182192
* @return string
183193
* @internal

src/Responses/DefaultResponse.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace donatj\MockWebServer\Responses;
4+
5+
use donatj\MockWebServer\MockWebServer;
6+
use donatj\MockWebServer\RequestInfo;
7+
use donatj\MockWebServer\ResponseInterface;
8+
9+
/**
10+
* The Built-In Default Response.
11+
* Results in an HTTP 200 with a JSON encoded version of the incoming Request
12+
*/
13+
class DefaultResponse implements ResponseInterface {
14+
15+
public function getRef() {
16+
return md5(MockWebServer::VND . '.default-ref');
17+
}
18+
19+
public function getBody( RequestInfo $request ) {
20+
return json_encode($request, JSON_PRETTY_PRINT) . "\n";
21+
}
22+
23+
public function getHeaders( RequestInfo $request ) {
24+
return [ 'Content-Type' => 'application/json' ];
25+
}
26+
27+
public function getStatus( RequestInfo $request ) {
28+
return 200;
29+
}
30+
}

0 commit comments

Comments
 (0)