Skip to content

Commit

Permalink
Merge pull request #439 from clue-labs/response-types
Browse files Browse the repository at this point in the history
Add factory methods for common HTML/JSON/plaintext/XML response types
  • Loading branch information
WyriHaximus authored Feb 3, 2022
2 parents 6acf1a7 + a49404c commit 0b4ed9f
Show file tree
Hide file tree
Showing 17 changed files with 566 additions and 270 deletions.
321 changes: 220 additions & 101 deletions README.md

Large diffs are not rendered by default.

13 changes: 3 additions & 10 deletions examples/51-server-hello-world.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
"Hello world\n"
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
return React\Http\Message\Response::plaintext(
"Hello World!\n"
);
});

Expand Down
11 changes: 2 additions & 9 deletions examples/52-server-count-visitors.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

require __DIR__ . '/../vendor/autoload.php';

$counter = 0;
$http = new React\Http\HttpServer(function (ServerRequestInterface $request) use (&$counter) {
return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) use (&$counter) {
return React\Http\Message\Response::plaintext(
"Welcome number " . ++$counter . "!\n"
);
});
Expand Down
13 changes: 3 additions & 10 deletions examples/53-server-whatsmyip.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
$body = "Your IP is: " . $request->getServerParams()['REMOTE_ADDR'];
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
$body = "Your IP is: " . $request->getServerParams()['REMOTE_ADDR'] . "\n";

return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
return React\Http\Message\Response::plaintext(
$body
);
});
Expand Down
11 changes: 2 additions & 9 deletions examples/54-server-query-parameter.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
$queryParams = $request->getQueryParams();

$body = 'The query parameter "foo" is not set. Click the following link ';
Expand All @@ -15,11 +12,7 @@
$body = 'The value of "foo" is: ' . htmlspecialchars($queryParams['foo']);
}

return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/html'
),
return React\Http\Message\Response::html(
$body
);
});
Expand Down
24 changes: 6 additions & 18 deletions examples/55-server-cookie-handling.php
Original file line number Diff line number Diff line change
@@ -1,33 +1,21 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
$key = 'react\php';

if (isset($request->getCookieParams()[$key])) {
$body = "Your cookie value is: " . $request->getCookieParams()[$key];
$body = "Your cookie value is: " . $request->getCookieParams()[$key] . "\n";

return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
return React\Http\Message\Response::plaintext(
$body
);
}

return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain',
'Set-Cookie' => urlencode($key) . '=' . urlencode('test;more')
),
"Your cookie has been set."
);
return React\Http\Message\Response::plaintext(
"Your cookie has been set.\n"
)->withHeader('Set-Cookie', urlencode($key) . '=' . urlencode('test;more'));
});

$socket = new React\Socket\SocketServer(isset($argv[1]) ? $argv[1] : '0.0.0.0:0');
Expand Down
22 changes: 9 additions & 13 deletions examples/56-server-sleep.php
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\Loop;
use React\Http\Message\Response;
use React\Promise\Promise;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
return new Promise(function ($resolve, $reject) {
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
$promise = new React\Promise\Promise(function ($resolve, $reject) {
Loop::addTimer(1.5, function() use ($resolve) {
$response = new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
"Hello world"
);
$resolve($response);
$resolve();
});
});

return $promise->then(function () {
return React\Http\Message\Response::plaintext(
"Hello world!\n"
);
});
});

$socket = new React\Socket\SocketServer(isset($argv[1]) ? $argv[1] : '0.0.0.0:0');
Expand Down
28 changes: 8 additions & 20 deletions examples/57-server-error-handling.php
Original file line number Diff line number Diff line change
@@ -1,30 +1,18 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;
use React\Promise\Promise;

require __DIR__ . '/../vendor/autoload.php';

$count = 0;
$http = new React\Http\HttpServer(function (ServerRequestInterface $request) use (&$count) {
return new Promise(function ($resolve, $reject) use (&$count) {
$count++;

if ($count%2 === 0) {
throw new Exception('Second call');
}
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) use (&$count) {
$count++;

$response = new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
"Hello World!\n"
);
if ($count % 2 === 0) {
throw new Exception('Second call');
}

$resolve($response);
});
return React\Http\Message\Response::plaintext(
"Hello World!\n"
);
});

$socket = new React\Socket\SocketServer(isset($argv[1]) ? $argv[1] : '0.0.0.0:0');
Expand Down
3 changes: 1 addition & 2 deletions examples/58-server-stream-response.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\Loop;
use React\Http\Message\Response;
use React\Stream\ThroughStream;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
if ($request->getMethod() !== 'GET' || $request->getUri()->getPath() !== '/') {
return new Response(Response::STATUS_NOT_FOUND);
}
Expand Down
41 changes: 12 additions & 29 deletions examples/59-server-json-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,32 @@
// $ php examples/59-server-json-api.php 8080
// $ curl -v http://localhost:8080/ -H 'Content-Type: application/json' -d '{"name":"Alice"}'

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
if ($request->getHeaderLine('Content-Type') !== 'application/json') {
return new Response(
Response::STATUS_UNSUPPORTED_MEDIA_TYPE,
array(
'Content-Type' => 'application/json'
),
json_encode(array('error' => 'Only supports application/json')) . "\n"
);
return Response::json(
array('error' => 'Only supports application/json')
)->withStatus(Response::STATUS_UNSUPPORTED_MEDIA_TYPE);
}

$input = json_decode($request->getBody()->getContents());
if (json_last_error() !== JSON_ERROR_NONE) {
return new Response(
Response::STATUS_BAD_REQUEST,
array(
'Content-Type' => 'application/json'
),
json_encode(array('error' => 'Invalid JSON data given')) . "\n"
);
return Response::json(
array('error' => 'Invalid JSON data given')
)->withStatus(Response::STATUS_BAD_REQUEST);
}

if (!isset($input->name) || !is_string($input->name)) {
return new Response(
Response::STATUS_UNPROCESSABLE_ENTITY,
array(
'Content-Type' => 'application/json'
),
json_encode(array('error' => 'JSON data does not contain a string "name" property')) . "\n"
);
return Response::json(
array('error' => 'JSON data does not contain a string "name" property')
)->withStatus(Response::STATUS_UNPROCESSABLE_ENTITY);
}

return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'application/json'
),
json_encode(array('message' => 'Hello ' . $input->name)) . "\n"
return Response::json(
array('message' => 'Hello ' . $input->name)
);
});

Expand Down
13 changes: 3 additions & 10 deletions examples/61-server-hello-world-https.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
<?php

use Psr\Http\Message\ServerRequestInterface;
use React\Http\Message\Response;

require __DIR__ . '/../vendor/autoload.php';

$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
"Hello world!\n"
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
return React\Http\Message\Response::plaintext(
"Hello World!\n"
);
});

Expand Down
6 changes: 1 addition & 5 deletions examples/62-server-form-upload.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,7 @@
HTML;

return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/html; charset=UTF-8'
),
return Response::html(
$html
);
};
Expand Down
14 changes: 3 additions & 11 deletions examples/63-server-streaming-request.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,16 @@ function (Psr\Http\Message\ServerRequestInterface $request) {
});

$body->on('end', function () use ($resolve, &$bytes){
$resolve(new React\Http\Message\Response(
React\Http\Message\Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
$resolve(React\Http\Message\Response::plaintext(
"Received $bytes bytes\n"
));
});

// an error occures e.g. on invalid chunked encoded data or an unexpected 'end' event
$body->on('error', function (Exception $e) use ($resolve, &$bytes) {
$resolve(new React\Http\Message\Response(
React\Http\Message\Response::STATUS_BAD_REQUEST,
array(
'Content-Type' => 'text/plain'
),
$resolve(React\Http\Message\Response::plaintext(
"Encountered error after $bytes bytes: {$e->getMessage()}\n"
));
)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST));
});
});
}
Expand Down
24 changes: 6 additions & 18 deletions examples/71-server-http-proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,17 @@
// $ php examples/71-server-http-proxy.php 8080
// $ curl -v --proxy http://localhost:8080 http://reactphp.org/

use Psr\Http\Message\RequestInterface;
use React\Http\Message\Response;
use RingCentral\Psr7;

require __DIR__ . '/../vendor/autoload.php';

// Note how this example uses the `HttpServer` without the `StreamingRequestMiddleware`.
// This means that this proxy buffers the whole request before "processing" it.
// As such, this is store-and-forward proxy. This could also use the advanced
// `StreamingRequestMiddleware` to forward the incoming request as it comes in.
$http = new React\Http\HttpServer(function (RequestInterface $request) {
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
if (strpos($request->getRequestTarget(), '://') === false) {
return new Response(
Response::STATUS_BAD_REQUEST,
array(
'Content-Type' => 'text/plain'
),
'This is a plain HTTP proxy'
);
return React\Http\Message\Response::plaintext(
"This is a plain HTTP proxy\n"
)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST);
}

// prepare outgoing client request by updating request-target and Host header
Expand All @@ -35,12 +27,8 @@
// pseudo code only: simply dump the outgoing request as a string
// left up as an exercise: use an HTTP client to send the outgoing request
// and forward the incoming response to the original client request
return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/plain'
),
Psr7\str($outgoing)
return React\Http\Message\Response::plaintext(
RingCentral\Psr7\str($outgoing)
);
});

Expand Down
6 changes: 1 addition & 5 deletions examples/99-server-benchmark-download.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,7 @@ public function getSize()
$http = new React\Http\HttpServer(function (ServerRequestInterface $request) {
switch ($request->getUri()->getPath()) {
case '/':
return new Response(
Response::STATUS_OK,
array(
'Content-Type' => 'text/html'
),
return Response::html(
'<html><a href="1g.bin">1g.bin</a><br/><a href="10g.bin">10g.bin</a></html>'
);
case '/1g.bin':
Expand Down
Loading

0 comments on commit 0b4ed9f

Please sign in to comment.