Builder::createUriBase()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 6
nop 1
dl 0
loc 13
rs 9.2222
c 0
b 0
f 0
1
<?php
2
namespace suda\framework\request;
3
4
use function array_key_exists;
5
use suda\framework\http\Request as RawRequest;
6
7
/**
8
 * 请求包装器
9
 * 包装PHP请求
10
 */
11
class Builder
12
{
13
14
    /**
15
     * HTTP请求
16
     *
17
     * @var RawRequest
18
     */
19
    protected $request;
20
21
    /**
22
     * @var array
23
     */
24
    protected $server;
25
26
    /**
27
     * 创建请求包装器
28
     *
29
     * @param RawRequest $request
30
     */
31
    public function __construct(RawRequest $request)
32
    {
33
        $this->request = $request;
34
        $this->server = $this->getFormatServer($request);
35
    }
36
37
    /**
38
     * 构建对象
39
     *
40
     * @param RequestWrapper $request
41
     * @return void
42
     */
43
    public function build(RequestWrapper $request)
44
    {
45
        $request->setServer($this->server);
46
        $request->setRemoteAddr($this->parseRemoteAddr());
47
        $method = strtoupper($request->getServer('request-method', 'GET'));
48
        $request->setMethod($method);
49
        $request->setHost($this->getHttpHost());
50
        $request->setSecure($this->getSecure());
51
        $request->setPort($this->getServerPort());
52
        $this->createUri($request);
53
        $request->setUriBase(static::createUriBase($request));
54
    }
55
56
    /**
57
     * 获取IP地址
58
     *
59
     * @return string
60
     */
61
    private function parseRemoteAddr():string
62
    {
63
        static $ipFrom = [
64
            'http-x-real-ip', // For Nginx
65
            'http-client-ip',
66
            'http-x-forwarded-for',
67
            'http-x-forwarded',
68
            'http-x-cluster-client-ip',
69
            'http-forwarded-for',
70
            'http-forwarded',
71
            'remote-addr',
72
        ];
73
74
        foreach ($ipFrom as $key) {
75
            if (array_key_exists($key, $this->server)) {
76
                $ip = $this->parseIpAddress($this->server[$key]);
77
                if ($ip !== null) {
78
                    return $ip;
79
                }
80
            }
81
        }
82
        return  '0.0.0.0';
83
    }
84
85
    /**
86
     * 解析IP字段
87
     * @param string $value
88
     * @return string|null
89
     */
90
    private function parseIpAddress(string $value)
91
    {
92
        $ipPart = explode(',', $value);
93
        $options = FILTER_FLAG_IPV4
94
            | FILTER_FLAG_IPV6
95
            | FILTER_FLAG_NO_PRIV_RANGE
96
            | FILTER_FLAG_NO_RES_RANGE;
97
        foreach ($ipPart as $ip) {
98
            $ip = trim($ip);
99
            if (filter_var($ip, FILTER_VALIDATE_IP, $options) !== false) {
100
                return $ip;
101
            }
102
        }
103
        return null;
104
    }
105
    
106
    /**
107
     * 从请求投中获取HOST
108
     *
109
     * @return string
110
     */
111
    private function getHttpHost():string
112
    {
113
        if (array_key_exists('host', $this->request->header())) {
114
            return explode(':', $this->request->header()['host'])[0];
115
        }
116
        return $this->server['server-name'] ?? 'localhost';
117
    }
118
119
    /**
120
     * 获取端口
121
     *
122
     * @return integer
123
     */
124
    private function getServerPort():int
125
    {
126
        if (array_key_exists('server-port', $this->server)) {
127
            return $this->server['server-port'];
128
        }
129
        return $this->getSecure()?443:80;
130
    }
131
132
    /**
133
     * 获取安全状态
134
     *
135
     * @return boolean
136
     */
137
    private function getSecure():bool
138
    {
139
        $https = array_key_exists('https', $this->server)
140
            && strcasecmp($this->server['https'], 'off') != 0;
141
        $scheme = array_key_exists('request-scheme', $this->server)
142
            && strcasecmp($this->server['request-scheme'], 'https') === 0;
143
        return $https || $scheme;
144
    }
145
146
    /**
147
     * 创建URI
148
     *
149
     * @param RequestWrapper $request
150
     * @return void
151
     */
152
    private function createUri(RequestWrapper $request)
153
    {
154
        if (array_key_exists('document-root', $this->server)) {
155
            $index = (new IndexFinder(null, $this->server['document-root']))->getIndexFile();
156
        } else {
157
            $index = '';
158
        }
159
        $request->setIndex($index);
160
        $url = new UriParser($this->server['request-uri'] ?? '/', $index);
161
        $request->setQueries($url->getQuery());
162
        $request->setUri($url->getUri());
163
    }
164
165
    /**
166
     * 获取URI基础部分
167
     *
168
     * @param RequestWrapper $request
169
     * @return string
170
     */
171
    public static function createUriBase(RequestWrapper $request)
172
    {
173
        $scheme = $request->isSecure()?'https':'http';
174
        $port = $request->getPort();
175
        if ($port == 80 && $scheme == 'http') {
176
            $port = '';
177
        } elseif ($port == 433 && $scheme == 'https') {
178
            $port = '';
179
        } else {
180
            $port = ':'.$port;
181
        }
182
        $base = $scheme.'://'. $request->getHost().$port;
183
        return $base;
184
    }
185
186
    /**
187
     * 构建环境数据
188
     *
189
     * @param RawRequest $request
190
     * @return array
191
     */
192
    private function getFormatServer(RawRequest $request)
193
    {
194
        $server = [];
195
        foreach ($request->server() as $key => $value) {
196
            $name = strtolower(str_replace('_', '-', $key));
197
            $server[$name] = $value;
198
        }
199
        return $server;
200
    }
201
}
202