Completed
Push — master ( 69cdb4...c2609a )
by Nazar
03:54
created

Request::execute_request()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 12
rs 9.4285
cc 2
eloc 10
nc 2
nop 0
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
	cs\User;
19
20
class Request {
21
	/**
22
	 * @var \React\Http\Request
23
	 */
24
	protected $request;
25
	/**
26
	 * @var \React\Http\Response
27
	 */
28
	protected $response;
29
	/**
30
	 * @var float
31
	 */
32
	protected $request_started;
33
	/**
34
	 * @param \React\Http\Request  $request
35
	 * @param \React\Http\Response $response
36
	 * @param float                $request_started
37
	 */
38
	function __construct ($request, $response, $request_started) {
39
		$this->request         = $request;
40
		$this->response        = $response;
41
		$this->request_started = $request_started;
42
	}
43
	/**
44
	 * @param string $data
45
	 *
46
	 * @throws ExitException
47
	 */
48
	function __invoke ($data) {
49
		$request = $this->request;
50
		$this->fill_superglobals(
51
			$this->prepare_superglobals($request, $data)
52
		);
53
		try {
54
			try {
55
				$this->execute_request();
56
			} catch (ExitException $e) {
57
				if ($e->getCode() >= 400) {
58
					Page::instance()->error($e->getMessage() ?: null, $e->getJson());
59
				}
60
			}
61
		} catch (\Exception $e) {
62
			// Handle generic exceptions to avoid server from stopping
63
		}
64
		$Response = System_response::instance();
65
		$this->response->writeHead($Response->code, $Response->headers);
66
		if ($Response->code >= 300 && $Response->code < 400) {
67
			$this->response->end();
68
		} elseif (is_resource($Response->body_stream)) {
69
			$position = ftell($Response->body_stream);
70
			rewind($Response->body_stream);
71
			while (!feof($Response->body_stream)) {
72
				$this->response->write(fread($Response->body_stream, 1024));
73
			}
74
			fseek($Response->body_stream, $position);
75
		} else {
76
			$this->response->end($Response->body);
77
		}
78
		$request->close();
79
		User::instance()->disable_memory_cache();
80
	}
81
	/**
82
	 * @param \React\HTTP\Request $request
83
	 * @param string              $data
84
	 *
85
	 * @return array
86
	 */
87
	protected function prepare_superglobals ($request, $data) {
88
		$SERVER = [
89
			'SERVER_SOFTWARE' => 'ReactPHP'
90
		];
91
		$COOKIE = [];
92
		$POST   = [];
93
		foreach ($request->getHeaders() as $key => $value) {
94
			if ($key == 'Content-Type') {
95
				$SERVER['CONTENT_TYPE'] = $value;
96
			} elseif ($key == 'Cookie') {
97
				$value = _trim(explode(';', $value));
98
				foreach ($value as $c) {
99
					$c             = explode('=', $c);
100
					$COOKIE[$c[0]] = $c[1];
101
				}
102
				unset($c);
103
			} else {
104
				$key                 = strtoupper(str_replace('-', '_', $key));
105
				$SERVER["HTTP_$key"] = $value;
106
			}
107
		}
108
		$SERVER['REQUEST_METHOD']  = $request->getMethod();
109
		$SERVER['REQUEST_URI']     = $request->getPath();
110
		$SERVER['QUERY_STRING']    = http_build_query($request->getQuery());
111
		$SERVER['REMOTE_ADDR']     = $request->remoteAddress;
112
		$GET                       = $request->getQuery();
113
		$SERVER['SERVER_PROTOCOL'] = 'HTTP/'.$request->getHttpVersion();
114
		if (isset($SERVER['CONTENT_TYPE'])) {
115
			if (strpos($SERVER['CONTENT_TYPE'], 'application/x-www-form-urlencoded') === 0) {
116
				parse_str($data, $POST);
117
			} elseif (preg_match('#^application/([^+\s]+\+)?json#', $SERVER['CONTENT_TYPE'])) {
118
				$POST = json_decode($data, true);
119
			}
120
		}
121
		return [
122
			'SERVER' => $SERVER,
123
			'COOKIE' => $COOKIE,
124
			'GET'    => $GET,
125
			'POST'   => $POST
126
		];
127
	}
128
	/**
129
	 * @param array $SUPERGLOBALS
130
	 *
131
	 * @throws ExitException
132
	 */
133
	protected function fill_superglobals ($SUPERGLOBALS) {
134
		// Hack: Filling $_SERVER is primarily needed for HybridAuth (many hard dependencies on `$_SERVER`)
135
		$_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...
136
		$_COOKIE  = $SUPERGLOBALS['COOKIE'];
137
		$_GET     = $SUPERGLOBALS['GET'];
138
		$_POST    = $SUPERGLOBALS['POST'];
139
		$_REQUEST = $SUPERGLOBALS['POST'] + $SUPERGLOBALS['GET'];
140
	}
141
	/**
142
	 * @throws ExitException
143
	 */
144
	protected function execute_request () {
145
		$Request = System_request::instance();
146
		$Request->init_from_globals();
147
		$Request->started = $this->request_started;
148
		System_response::instance()->init_with_typical_default_settings();
149
		$L            = Language::instance(true);
150
		$url_language = $L->url_language();
151
		if ($url_language) {
152
			$L->change($url_language);
153
		}
154
		App::instance()->execute();
155
	}
156
}
157