Completed
Push — master ( b7b84b...78616b )
by Nazar
04:19
created

Request::cleanup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
c 5
b 1
f 1
dl 0
loc 7
rs 9.4285
cc 1
eloc 3
nc 1
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 (is_resource($Response->body_stream)) {
67
			$position = ftell($Response->body_stream);
68
			rewind($Response->body_stream);
69
			while (!feof($Response->body_stream)) {
70
				$this->response->write(fread($Response->body_stream, 1024));
71
			}
72
			fseek($Response->body_stream, $position);
73
		} else {
74
			$this->response->end($Response->body);
75
		}
76
		$request->close();
77
		User::instance()->disable_memory_cache();
78
	}
79
	/**
80
	 * @param \React\HTTP\Request $request
81
	 * @param string              $data
82
	 *
83
	 * @return array
84
	 */
85
	protected function prepare_superglobals ($request, $data) {
86
		$SERVER = [
87
			'SERVER_SOFTWARE' => 'ReactPHP'
88
		];
89
		$COOKIE = [];
90
		$POST   = [];
91
		foreach ($request->getHeaders() as $key => $value) {
92
			if ($key == 'Content-Type') {
93
				$SERVER['CONTENT_TYPE'] = $value;
94
			} elseif ($key == 'Cookie') {
95
				$value = _trim(explode(';', $value));
96
				foreach ($value as $c) {
97
					$c             = explode('=', $c);
98
					$COOKIE[$c[0]] = $c[1];
99
				}
100
				unset($c);
101
			} else {
102
				$key                 = strtoupper(str_replace('-', '_', $key));
103
				$SERVER["HTTP_$key"] = $value;
104
			}
105
		}
106
		$SERVER['REQUEST_METHOD']  = $request->getMethod();
107
		$SERVER['REQUEST_URI']     = $request->getPath();
108
		$SERVER['QUERY_STRING']    = http_build_query($request->getQuery());
109
		$SERVER['REMOTE_ADDR']     = $request->remoteAddress;
110
		$GET                       = $request->getQuery();
111
		$SERVER['SERVER_PROTOCOL'] = 'HTTP/'.$request->getHttpVersion();
112
		if (isset($SERVER['CONTENT_TYPE'])) {
113
			if (strpos($SERVER['CONTENT_TYPE'], 'application/x-www-form-urlencoded') === 0) {
114
				parse_str($data, $POST);
115
			} elseif (preg_match('#^application/([^+\s]+\+)?json#', $SERVER['CONTENT_TYPE'])) {
116
				$POST = json_decode($data, true);
117
			}
118
		}
119
		return [
120
			'SERVER' => $SERVER,
121
			'COOKIE' => $COOKIE,
122
			'GET'    => $GET,
123
			'POST'   => $POST
124
		];
125
	}
126
	/**
127
	 * @param array $SUPERGLOBALS
128
	 *
129
	 * @throws ExitException
130
	 */
131
	protected function fill_superglobals ($SUPERGLOBALS) {
132
		// Hack: Filling $_SERVER is primarily needed for HybridAuth (many hard dependencies on `$_SERVER`)
133
		$_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...
134
		$_COOKIE  = $SUPERGLOBALS['COOKIE'];
135
		$_GET     = $SUPERGLOBALS['GET'];
136
		$_POST    = $SUPERGLOBALS['POST'];
137
		$_REQUEST = $SUPERGLOBALS['POST'] + $SUPERGLOBALS['GET'];
138
	}
139
	/**
140
	 * @throws ExitException
141
	 */
142
	protected function execute_request () {
143
		$Request = System_request::instance();
144
		$Request->init_from_globals();
145
		$Request->started = $this->request_started;
146
		System_response::instance()->init_with_typical_default_settings();
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