Passed
Push — master ( 13d26f...cd746f )
by 世昌
02:18
created

Request::buildFromServer()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 14
rs 9.9
1
<?php
2
namespace nebula\request;
3
4
use nebula\request\Request;
5
use nebula\request\header\HeaderItem;
6
use nebula\request\attribute\AttributeTrait;
7
use nebula\request\attribute\AttributeAbstract;
8
9
10
/**
11
 * HTTP请求解析器
12
 *
13
 */
14
class Request  implements AttributeAbstract {
15
16
    use AttributeTrait;
17
    
18
    /**
19
     * 请求方法
20
     *
21
     * @var string
22
     */
23
    protected $method;
24
25
    /**
26
     * 请求头
27
     *
28
     * @var HeaderItem[]
29
     */
30
    protected $headers;
31
32
    /**
33
     * 服务器属性
34
     *
35
     * @var array
36
     */
37
    protected $server;
38
39
    /**
40
     * 构建请求
41
     *
42
     * @param string $method
43
     * @param string $uri
44
     * @param HeaderItem[] $headers
45
     */
46
    public function __construct(string $method, string $uri, array $headers = []) {
47
        $this->uri = $uri;
48
        $this->method = strtoupper($method);
49
        $this->headers = $headers;
50
    }
51
52
    /**
53
     * Get 请求方法
54
     *
55
     * @return  string
56
     */ 
57
    public function getMethod()
58
    {
59
        return $this->method;
60
    }
61
62
    /**
63
     * 获取请求头
64
     *
65
     * @param string $name
66
     * @param mixed $default
67
     * @return mixed
68
     */
69
    public function getHeader(string $name, $default =null) {
70
        if (array_key_exists(strtolower($name), $this->headers)) {
71
            return $this->headers[$name];
72
        }
73
        return $default;
74
    }
75
76
    /**
77
     * 判断请求头
78
     *
79
     * @param string $name
80
     * @return boolean
81
     */
82
    public function hasHeader(string $name) {
83
        return $this->getHeader($name) !== null;
84
    }
85
86
    /**
87
     * 获取请求IP
88
     *
89
     * @return string
90
     */
91
    public function ip()
92
    {
93
        static $ipFrom = ['HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP','HTTP_FORWARDED_FOR','HTTP_FORWARDED','REMOTE_ADDR'];
94
        foreach ($ipFrom as $key) {
95
            if (array_key_exists($key, $_SERVER)) {
96
                foreach (explode(',', $_SERVER[$key]) as $ip) {
97
                    $ip = trim($ip);
98
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
99
                        return $ip;
100
                    }
101
                }
102
            }
103
        }
104
        return  '127.0.0.1';
105
    }
106
    
107
    /**
108
     * 从环境构建请求
109
     *
110
     * @param array $server
111
     * @return Request
112
     */
113
    public static function buildFromServer(array $server = null): Request {
114
        if ($server === null) {
115
            $server = $_SERVER;
116
            $simulate = true;
117
        }
118
        $method = strtoupper($server['REQUEST_METHOD'] ?? 'GET');
119
        $uri = $server['REQUEST_URI']??'/';
120
        $headers  = HeaderItem::buildFromServer($server);
0 ignored issues
show
Bug introduced by
It seems like $server can also be of type null; however, parameter $server of nebula\request\header\He...Item::buildFromServer() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

120
        $headers  = HeaderItem::buildFromServer(/** @scrutinizer ignore-type */ $server);
Loading history...
121
        $request =  new Request($method, $uri, $headers);
122
        $request->setDocumentRoot($server['DOCUMENT_ROOT']);
123
        if ($simulate) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $simulate does not seem to be defined for all execution paths leading up to this point.
Loading history...
124
            $request->setServer($server);
0 ignored issues
show
Bug introduced by
It seems like $server can also be of type null; however, parameter $server of nebula\request\Request::setServer() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

124
            $request->setServer(/** @scrutinizer ignore-type */ $server);
Loading history...
125
        }
126
        return $request;
127
    }
128
129
    /**
130
     * Get 服务器属性
131
     *
132
     * @return  array
133
     */ 
134
    public function getServer()
135
    {
136
        return $this->server ?? $_SERVER;
137
    }
138
139
    /**
140
     * Set 服务器属性
141
     *
142
     * @param  array  $server  服务器属性
143
     *
144
     * @return  self
145
     */ 
146
    public function setServer(array $server)
147
    {
148
        $this->server = $server;
149
150
        return $this;
151
    }
152
}