Completed
Push — master ( 561c31...ac170c )
by Nazar
04:13
created

Request   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 7

Importance

Changes 7
Bugs 1 Features 2
Metric Value
wmc 20
c 7
b 1
f 2
lcom 0
cbo 7
dl 0
loc 145
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
C __invoke() 0 31 7
C prepare_superglobals() 0 41 8
A fill_superglobals() 0 8 1
A execute_request() 0 19 2
A cleanup() 0 6 1
1
<?php
2
/**
3
 * @package   Http server
4
 * @category  modules
5
 * @author    Nazar Mokrynskyi <[email protected]>
6
 * @copyright Copyright (c) 2015-2016, Nazar Mokrynskyi
7
 * @license   MIT License, see license.txt
8
 */
9
namespace cs\modules\Http_server;
10
use
11
	cs\_SERVER,
12
	cs\App,
13
	cs\ExitException,
14
	cs\Language,
15
	cs\Page,
16
	cs\Request as System_request,
17
	cs\Response as System_response;
18
19
class Request {
20
	/**
21
	 * @var \React\Http\Request
22
	 */
23
	protected $request;
24
	/**
25
	 * @var \React\Http\Response
26
	 */
27
	protected $response;
28
	/**
29
	 * @param \React\Http\Request  $request
30
	 * @param \React\Http\Response $response
31
	 */
32
	function __construct ($request, $response) {
33
		$this->request  = $request;
34
		$this->response = $response;
35
	}
36
	/**
37
	 * @param string $data
38
	 *
39
	 * @throws ExitException
40
	 */
41
	function __invoke ($data) {
42
		$request = $this->request;
43
		$this->fill_superglobals(
44
			$this->prepare_superglobals($request, $data)
45
		);
46
		try {
47
			try {
48
				$this->execute_request();
49
			} catch (ExitException $e) {
50
				if ($e->getCode() >= 400) {
51
					Page::instance()->error($e->getMessage() ?: null, $e->getJson());
52
				}
53
			}
54
		} catch (\Exception $e) {
55
			// Handle generic exceptions to avoid server from stopping
56
		}
57
		$Response = System_response::instance();
58
		$this->response->writeHead($Response->code, $Response->headers);
59
		if (is_resource($Response->body_stream)) {
60
			$position = ftell($Response->body_stream);
61
			rewind($Response->body_stream);
62
			while (!feof($Response->body_stream)) {
63
				$this->response->write(fread($Response->body_stream, 1024));
64
			}
65
			fseek($Response->body_stream, $position);
66
		} else {
67
			$this->response->end($Response->body);
68
		}
69
		$this->cleanup();
70
		$request->close();
71
	}
72
	/**
73
	 * @param \React\HTTP\Request $request
74
	 * @param string              $data
75
	 *
76
	 * @return array
77
	 */
78
	protected function prepare_superglobals ($request, $data) {
79
		$SERVER = [
80
			'SERVER_SOFTWARE' => 'ReactPHP'
81
		];
82
		$COOKIE = [];
83
		$POST   = [];
84
		foreach ($request->getHeaders() as $key => $value) {
85
			if ($key == 'Content-Type') {
86
				$SERVER['CONTENT_TYPE'] = $value;
87
			} elseif ($key == 'Cookie') {
88
				$value = _trim(explode(';', $value));
89
				foreach ($value as $c) {
90
					$c             = explode('=', $c);
91
					$COOKIE[$c[0]] = $c[1];
92
				}
93
				unset($c);
94
			} else {
95
				$key                 = strtoupper(str_replace('-', '_', $key));
96
				$SERVER["HTTP_$key"] = $value;
97
			}
98
		}
99
		$SERVER['REQUEST_METHOD']  = $request->getMethod();
100
		$SERVER['REQUEST_URI']     = $request->getPath();
101
		$SERVER['QUERY_STRING']    = http_build_query($request->getQuery());
102
		$SERVER['REMOTE_ADDR']     = $request->remoteAddress;
103
		$GET                       = $request->getQuery();
104
		$SERVER['SERVER_PROTOCOL'] = 'HTTP/'.$request->getHttpVersion();
105
		if (isset($SERVER['CONTENT_TYPE'])) {
106
			if (strpos($SERVER['CONTENT_TYPE'], 'application/x-www-form-urlencoded') === 0) {
107
				parse_str($data, $POST);
108
			} elseif (preg_match('#^application/([^+\s]+\+)?json#', $SERVER['CONTENT_TYPE'])) {
109
				$POST = json_decode($data, true);
110
			}
111
		}
112
		return [
113
			'SERVER' => $SERVER,
114
			'COOKIE' => $COOKIE,
115
			'GET'    => $GET,
116
			'POST'   => $POST
117
		];
118
	}
119
	/**
120
	 * @param array $SUPERGLOBALS
121
	 *
122
	 * @throws ExitException
123
	 */
124
	protected function fill_superglobals ($SUPERGLOBALS) {
125
		// Hack: Filling $_SERVER is primarily needed for HybridAuth (many hard dependencies on `$_SERVER`)
126
		$_SERVER  = new _SERVER($SUPERGLOBALS['SERVER']);
0 ignored issues
show
Deprecated Code introduced by
The class cs\_SERVER has been deprecated with message: Use `cs\Request` instead, it provides very similar, but more powerful interface

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
127
		$_COOKIE  = $SUPERGLOBALS['COOKIE'];
128
		$_GET     = $SUPERGLOBALS['GET'];
129
		$_POST    = $SUPERGLOBALS['POST'];
130
		$_REQUEST = $SUPERGLOBALS['POST'] + $SUPERGLOBALS['GET'];
131
	}
132
	/**
133
	 * @throws ExitException
134
	 */
135
	protected function execute_request () {
136
		System_request::instance()->init_from_globals();
137
		System_response::instance()->init(
138
			'',
139
			null,
140
			[
141
				'Content-Type' => 'text/html; charset=utf-8',
142
				'Vary'         => 'Accept-Language,User-Agent,Cookie'
143
			],
144
			200,
145
			$_SERVER['SERVER_PROTOCOL']
146
		);
147
		$L            = Language::instance(true);
148
		$url_language = $L->url_language();
149
		if ($url_language) {
150
			$L->change($url_language);
151
		}
152
		App::instance()->execute();
153
	}
154
	/**
155
	 * Various cleanups after processing of current request to free used memory
156
	 */
157
	function cleanup () {
158
		/**
159
		 * Clean objects pool
160
		 */
161
		objects_pool([]);
162
	}
163
}
164