Skip to content

Commit 8d72663

Browse files
committed
[add] server, http & session objects v1
1 parent d903700 commit 8d72663

File tree

5 files changed

+352
-0
lines changed

5 files changed

+352
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
.buildpath
3+
.project
4+
.settings/
5+
composer.lock
6+
vendor/

composer.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name" : "phpmv/ubiquity-reactphp",
3+
"description" : "ReactPHP extension for Ubiquity framework",
4+
"type" : "extension",
5+
"keywords" : [
6+
"php",
7+
"framework",
8+
"mvc",
9+
"orm",
10+
"server"
11+
],
12+
"require" : {
13+
"php" : ">7.0",
14+
"react/http" : "^0.8.4",
15+
"wyrihaximus/react-http-middleware-session" : "^2.1"
16+
},
17+
"license" : "Apache-2.0",
18+
"authors" : [{
19+
"name" : "Jean-Christophe HERON",
20+
"email" : "myaddressmail@gmail.com",
21+
"role" : "Lead developer"
22+
}
23+
],
24+
"autoload" : {
25+
"psr-4" : {
26+
"Ubiquity\\" : "src/Ubiquity/"
27+
}
28+
},
29+
"extra" : {
30+
"branch-alias" : {
31+
"dev-master" : "1.0.x-dev"
32+
}
33+
},
34+
"require-dev" : {
35+
"phpmv/ubiquity": "dev-master"
36+
}
37+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<?php
2+
3+
namespace Ubiquity\servers\react;
4+
5+
use React\Cache\ArrayCache;
6+
use Ubiquity\utils\http\foundation\ReactHttp;
7+
use Ubiquity\utils\http\session\ReactPhpSession;
8+
use WyriHaximus\React\Http\Middleware\SessionMiddleware;
9+
10+
/**
11+
* React Http server for Ubiquity.
12+
* Ubiquity\servers\react$ReactServer
13+
* This class is part of Ubiquity
14+
* @author jcheron <myaddressmail@gmail.com>
15+
* @version 1.0.0
16+
*
17+
*/
18+
class ReactServer {
19+
private $server;
20+
private $sessionCookieOptions=[0,'','',false,false];
21+
22+
public function init($config,$basedir){
23+
$httpInstance=new ReactHttp();
24+
$sessionInstance=new ReactPhpSession();
25+
$this->server = new \React\Http\Server([
26+
new SessionMiddleware($config['sessionName']??'cookie_name',new ArrayCache(),$this->sessionCookieOptions),
27+
function (\Psr\Http\Message\ServerRequestInterface $request) use($config,$httpInstance,$sessionInstance,$basedir){
28+
$_GET['c']='';
29+
$uri = ltrim(urldecode(parse_url( $request->getUri()->getPath(), PHP_URL_PATH)),'/');
30+
if ($uri==null || !file_exists($basedir . '/../' .$uri)) {
31+
$_GET['c'] = $uri;
32+
}else{
33+
$headers=$request->getHeaders();
34+
return new \React\Http\Response(
35+
$httpInstance->getResponseCode(),
36+
$headers,
37+
file_get_contents($basedir . '/../' .$uri)
38+
);
39+
}
40+
41+
$headers=$request->getHeaders();
42+
$httpInstance->setRequest($request);
43+
$sessionInstance->setRequest($request);
44+
$this->parseRequest($request);
45+
\ob_start ();
46+
\Ubiquity\controllers\Startup::setHttpInstance($httpInstance);
47+
\Ubiquity\controllers\Startup::setSessionInstance($sessionInstance);
48+
\Ubiquity\controllers\Startup::run($config);
49+
$content=ob_get_clean();
50+
51+
return new \React\Http\Response(http_response_code(),$headers,$content);
52+
}
53+
]);
54+
}
55+
56+
/**
57+
* Sets the session cookie options
58+
* @param int $expiresAt
59+
* @param string $path
60+
* @param string $domain
61+
* @param boolean $secure
62+
* @param boolean $httpOnly
63+
*/
64+
public function setSessionCookieOptions($expiresAt=0,$path='',$domain='', $secure=false,$httpOnly=false){
65+
$this->sessionCookieOptions=[$expiresAt,$path,$domain,$secure,$httpOnly];
66+
}
67+
68+
public function run($port){
69+
$loop = \React\EventLoop\Factory::create();
70+
$socket = new \React\Socket\Server($port, $loop);
71+
$this->server->listen($socket);
72+
73+
echo "Running react server at http://127.0.0.1:$port\n";
74+
75+
$loop->run();
76+
}
77+
78+
public function parseRequest(\Psr\Http\Message\ServerRequestInterface $request){
79+
$method=$request->getMethod();
80+
$uri=$request->getUri()->getPath();
81+
$parameters=$request->getQueryParams();
82+
$parsedBody=$request->getParsedBody();
83+
$headers=$request->getHeaders();
84+
$server = array_replace([
85+
'SERVER_NAME' => 'localhost',
86+
'SERVER_PORT' => 80,
87+
'HTTP_HOST' => 'localhost',
88+
'HTTP_USER_AGENT' => 'Ubiquity',
89+
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
90+
'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
91+
'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
92+
'REMOTE_ADDR' => '127.0.0.1',
93+
'SCRIPT_NAME' => '',
94+
'SCRIPT_FILENAME' => '',
95+
'SERVER_PROTOCOL' => 'HTTP/1.1',
96+
'REQUEST_TIME' => time(),
97+
], $request->getServerParams());
98+
$server['PATH_INFO'] = '';
99+
$server['REQUEST_METHOD'] = strtoupper($method);
100+
$components = parse_url($uri);
101+
if (isset($components['host'])) {
102+
$server['SERVER_NAME'] = $components['host'];
103+
$server['HTTP_HOST'] = $components['host'];
104+
}
105+
if (isset($components['scheme'])) {
106+
if ('https' === $components['scheme']) {
107+
$server['HTTPS'] = 'on';
108+
$server['SERVER_PORT'] = 443;
109+
} else {
110+
unset($server['HTTPS']);
111+
$server['SERVER_PORT'] = 80;
112+
}
113+
}
114+
if (isset($components['port'])) {
115+
$server['SERVER_PORT'] = $components['port'];
116+
$server['HTTP_HOST'] .= ':'.$components['port'];
117+
}
118+
if (isset($components['user'])) {
119+
$server['PHP_AUTH_USER'] = $components['user'];
120+
}
121+
if (isset($components['pass'])) {
122+
$server['PHP_AUTH_PW'] = $components['pass'];
123+
}
124+
if (!isset($components['path'])) {
125+
$components['path'] = '/';
126+
}
127+
switch (strtoupper($method)) {
128+
case 'POST':
129+
case 'PUT':
130+
case 'DELETE':
131+
if (!isset($server['CONTENT_TYPE'])) {
132+
$server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
133+
}
134+
// no break
135+
case 'PATCH':
136+
$query = [];
137+
break;
138+
default:
139+
$query = $parameters;
140+
break;
141+
}
142+
$queryString = '';
143+
if (isset($components['query'])) {
144+
parse_str(html_entity_decode($components['query']), $qs);
145+
if ($query) {
146+
$query = array_replace($qs, $query);
147+
$queryString = http_build_query($query, '', '&');
148+
} else {
149+
$query = $qs;
150+
$queryString = $components['query'];
151+
}
152+
} elseif ($query) {
153+
$queryString = http_build_query($query, '', '&');
154+
}
155+
$server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : '');
156+
$server['QUERY_STRING'] = $queryString;
157+
if(isset($headers['X-Requested-With']) && array_search('XMLHttpRequest',$headers['X-Requested-With'])!==false){
158+
$server ['HTTP_X_REQUESTED_WITH']='XMLHttpRequest';
159+
}
160+
if(strtoupper($method)==='POST'){
161+
$_POST=$parsedBody;
162+
}
163+
if(sizeof($parameters)>0){
164+
$_GET=array_merge($_GET,$parameters);
165+
}
166+
$_SERVER=$server;
167+
}
168+
}
169+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Ubiquity\utils\http\foundation;
4+
5+
/**
6+
* Http instance for ReactPHP.
7+
* Ubiquity\utils\http\foundation$ReactHttp
8+
* This class is part of Ubiquity
9+
* @author jcheron <myaddressmail@gmail.com>
10+
* @version 1.0.0
11+
*
12+
*/
13+
class ReactHttp extends AbstractHttp {
14+
private $headers;
15+
private $responseCode=200;
16+
private $request;
17+
18+
19+
public function getAllHeaders() {
20+
return $this->headers;
21+
}
22+
23+
public function header($key,$value,$replace=null,$http_response_code=null) {
24+
$this->headers[$key]=$value;
25+
if(isset($http_response_code)){
26+
$this->responseCode=$http_response_code;
27+
}
28+
}
29+
30+
/**
31+
* @return int
32+
*/
33+
public function getResponseCode() {
34+
return $this->responseCode;
35+
}
36+
37+
/**
38+
* @param mixed $headers
39+
*/
40+
private function setHeaders($headers) {
41+
foreach ($headers as $k=>$header){
42+
if(is_array($header) && sizeof($header)==1){
43+
$this->headers[$k] = current($header);
44+
}else{
45+
$this->headers[$k]=$header;
46+
}
47+
}
48+
}
49+
50+
/**
51+
* @param int $responseCode
52+
*/
53+
public function setResponseCode($responseCode) {
54+
$this->responseCode = $responseCode;
55+
}
56+
57+
public function headersSent(string &$file = null, int &$line = null) {
58+
return false;
59+
}
60+
61+
public function getInput() {
62+
return $this->request->getParsedBody();
63+
}
64+
/**
65+
* @param mixed $request
66+
*/
67+
public function setRequest($request) {
68+
$this->request=$request;
69+
$this->setHeaders($request->getHeaders());
70+
}
71+
}
72+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace Ubiquity\utils\http\session;
4+
5+
use WyriHaximus\React\Http\Middleware\SessionMiddleware;
6+
7+
/**
8+
* Session object for ReactPHP.
9+
* Ubiquity\utils\http\session$ReactPhpSession
10+
* This class is part of Ubiquity
11+
* @author jcheron <myaddressmail@gmail.com>
12+
* @version 1.0.0
13+
*
14+
*/
15+
class ReactPhpSession extends AbstractSession {
16+
17+
/**
18+
* @var \WyriHaximus\React\Http\Middleware\Session
19+
*/
20+
private $sessionInstance;
21+
22+
private function getContents(){
23+
return $this->sessionInstance->getContents();
24+
}
25+
26+
public function setRequest(\Psr\Http\Message\ServerRequestInterface $request){
27+
$this->sessionInstance=$request->getAttribute(SessionMiddleware::ATTRIBUTE_NAME);
28+
}
29+
30+
public function set($key, $value) {
31+
$contents=$this->getContents();
32+
$contents[$key]=$value;
33+
$this->sessionInstance->setContents($contents);
34+
}
35+
36+
public function getAll() {
37+
return $this->getContents();
38+
}
39+
40+
public function get($key, $default = null) {
41+
$contents=$this->getContents();
42+
return $contents[$key]??$default;
43+
}
44+
45+
public function start($name = null) {
46+
$this->sessionInstance->begin();
47+
}
48+
49+
public function exists($key) {
50+
$contents=$this->getContents();
51+
return isset($contents[$key]);
52+
}
53+
54+
public function terminate() {
55+
$this->sessionInstance->end();
56+
}
57+
58+
public function isStarted() {
59+
return $this->sessionInstance->isActive();
60+
}
61+
62+
public function delete($key) {
63+
$contents=$this->getContents();
64+
unset($contents[$key]);
65+
$this->sessionInstance->setContents($contents);
66+
}
67+
}
68+

0 commit comments

Comments
 (0)