Completed
Push — master ( e483df...e03548 )
by Nazar
04:05
created

Request::execute()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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