Issues (32)

src/Powered/Swoole/Client.php (7 issues)

1
<?php
2
/**
3
 * HTTP client by swoole
4
 * User: moyo
5
 * Date: 12/09/2017
6
 * Time: 3:07 PM
7
 */
8
9
namespace Carno\HTTP\Powered\Swoole;
10
11
use function Carno\Coroutine\await;
12
use Carno\HTTP\Contracts\Powered\Client as API;
13
use Carno\HTTP\Exception\RequestTimeoutException;
14
use Carno\HTTP\Options;
15
use Carno\HTTP\Powered\Swoole\Chips\Http;
16
use Carno\HTTP\Powered\Swoole\Chips\Socket;
17
use Carno\HTTP\Powered\Swoole\Chips\Throws;
18
use Carno\HTTP\Standard\Helper;
19
use Carno\Net\Address;
20
use Carno\Pool\Managed;
21
use Carno\Pool\Poolable;
22
use Carno\Promise\Promise;
23
use Carno\Promise\Promised;
24
use Psr\Http\Message\RequestInterface as Request;
25
use Swoole\Http\Client as SWHClient;
0 ignored issues
show
The type Swoole\Http\Client was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
27
class Client implements API, Poolable
28
{
29
    use Helper, Managed;
30
    use Http, Socket, Throws;
0 ignored issues
show
The trait Carno\HTTP\Powered\Swoole\Chips\Throws requires some properties which are not provided by Carno\HTTP\Powered\Swoole\Client: $statusCode, $errCode
Loading history...
The trait Carno\HTTP\Powered\Swoole\Chips\Socket requires some properties which are not provided by Carno\HTTP\Powered\Swoole\Client: $opcode, $data, $statusCode
Loading history...
The trait Carno\HTTP\Powered\Swoole\Chips\Http requires some properties which are not provided by Carno\HTTP\Powered\Swoole\Client: $statusCode, $headers, $body
Loading history...
31
32
    /**
33
     * @var bool
34
     */
35
    private $keepalive = false;
36
37
    /**
38
     * @var Address
39
     */
40
    private $connect = null;
41
42
    /**
43
     * @var bool
44
     */
45
    private $closing = false;
46
47
    /**
48
     * @var SWHClient
49
     */
50
    private $http = null;
51
52
    /**
53
     * Client constructor.
54
     * @param Address $connect
55
     * @param bool $keepalive
56
     */
57
    public function __construct(Address $connect, bool $keepalive = false)
58
    {
59
        $this->connect = $connect;
60
        $this->keepalive = $keepalive;
61
    }
62
63
    /**
64
     * @param Request $request
65
     * @param Options $options
66
     */
67
    private function initialize(Request $request, Options $options) : void
68
    {
69
        $this->http = new SWHClient(
70
            $this->connect->host(),
71
            $this->connect->port(),
72
            in_array($scheme = $request->getUri()->getScheme(), ['https', 'wss'])
73
        );
74
75
        $this->http->set([
76
            'open_tcp_nodelay' => true,
77
            'keep_alive' => $this->keepalive || $socket = in_array($scheme, ['ws', 'wss']),
78
        ]);
79
80
        ($socket ?? null) && $this->http->set(['websocket_mask' => true]);
81
82
        if ($options->hasProxy()) {
83
            $px = $options->getProxy();
84
            $pxc = [
85
                'http_proxy_host' => $px['host'],
86
                'http_proxy_port' => $px['port'],
87
            ];
88
            $px['user'] && $pxc['http_proxy_user'] = $px['user'];
89
            $px['pass'] && $pxc['http_proxy_password'] = $px['pass'];
90
            $this->http->set($pxc);
91
        }
92
93
        $this->http->on('connect', function () {
94
            $this->http->on('error', [$this, 'failure']);
95
            $this->http->on('close', [$this, 'closing']);
96
        });
97
    }
98
99
    /**
100
     * @param string $ev
101
     */
102
    private function finalize(string $ev) : void
0 ignored issues
show
The parameter $ev is not used and could be removed. ( Ignorable by Annotation )

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

102
    private function finalize(/** @scrutinizer ignore-unused */ string $ev) : void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
103
    {
104
        if (isset($this->http)) {
105
            unset($this->http);
106
            $this->disconnect();
107
        }
108
    }
109
110
    /**
111
     */
112
    private function disconnect() : void
113
    {
114
        $this->closed()->pended() && $this->closed()->resolve();
115
    }
116
117
    /**
118
     * @return Promised
119
     */
120
    public function connect() : Promised
121
    {
122
        return Promise::resolved();
123
    }
124
125
    /**
126
     * @return Promised
127
     */
128
    public function heartbeat() : Promised
129
    {
130
        return Promise::resolved();
131
    }
132
133
    /**
134
     * @return Promised
135
     */
136
    public function close() : Promised
137
    {
138
        if ($this->closing) {
139
            goto CLOSED_STA;
140
        }
141
142
        $this->closing = true;
143
144
        if (isset($this->http) && $this->http->isConnected()) {
145
            $this->http->close();
146
        } else {
147
            $this->disconnect();
148
        }
149
150
        CLOSED_STA:
151
152
        return $this->closed();
153
    }
154
155
    /**
156
     * @param SWHClient $c
157
     */
158
    public function failure(SWHClient $c = null) : void
0 ignored issues
show
The parameter $c is not used and could be removed. ( Ignorable by Annotation )

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

158
    public function failure(/** @scrutinizer ignore-unused */ SWHClient $c = null) : void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
159
    {
160
        $this->finalize('error');
161
    }
162
163
    /**
164
     * @param SWHClient $c
165
     */
166
    public function closing(SWHClient $c = null) : void
0 ignored issues
show
The parameter $c is not used and could be removed. ( Ignorable by Annotation )

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

166
    public function closing(/** @scrutinizer ignore-unused */ SWHClient $c = null) : void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
167
    {
168
        $this->finalize('close');
169
    }
170
171
    /**
172
     * @param Request $request
173
     * @param Options $options
174
     * @return Promised
175
     */
176
    public function execute(Request $request, Options $options) : Promised
177
    {
178
        if (is_null($this->http)) {
179
            $this->initialize($request, $options);
180
        }
181
182
        // config init -->
183
184
        $this->http->set(['timeout' => $options->ttOverall > 0 ? round($options->ttOverall / 1000, 3) : -1]);
185
186
        // host filter -->
187
188
        if ($request->hasHeader('Host') && filter_var($request->getHeaderLine('Host'), FILTER_VALIDATE_IP)) {
189
            $request->withoutHeader('Host');
190
        }
191
192
        // keepalive parser -->
193
194
        if (!$this->keepalive &&
195
            (!$request->hasHeader('Connection') ||
196
                ($request->hasHeader('Connection') &&
197
                    $request->getHeaderLine('Connection') !== 'close'
198
                )
199
            )
200
        ) {
201
            $request->withHeader('Connection', 'close');
202
        }
203
204
        // set headers -->
205
206
        $this->http->setHeaders($this->getHeaderLines($request));
207
208
        // programme init -->
209
210
        list($executor, $receiver) =
211
            $request->getMethod() === 'UPGRADE'
212
                ? $this->socket($request)
213
                : $this->http($request)
214
        ;
215
216
        // executing -->
217
218
        return await($executor, $receiver, $options->ttOverall, RequestTimeoutException::class, $request->getUri());
219
    }
220
}
221