Completed
Push — master ( 6e012d...8fc772 )
by Greg
02:13
created

BrowserMob::filterResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
namespace Codeception\Extension;
3
4
use Codeception\Module;
5
use Codeception\Exception\ModuleException;
6
use Codeception\Exception\ModuleConfigException;
7
use \PHPBrowserMobProxy_Client as BMP;
8
use \Requests;
9
use \RuntimeException;
10
11
/**
12
 * @method void _open()
13
 * @method void _close()
14
 * @method string _newHar(string $label='')
15
 * @method string _newPage(string $label='')
16
 * @method string _blacklist(string $regexp, integer $status_code)
17
 * @method string _whitelist(string $regexp, integer $status_code)
18
 * @method string _basicAuth(string $domain, string[] $options)
19
 * @method string _headers(string[] $options)
20
 * @method string _responseInterceptor(string $js)
21
 * @method string _requestInterceptor(string $js)
22
 * @method Requests_Response _limits(string[] $options)
23
 * @method Requests_Response _timeouts(string[] $options)
24
 * @method string _remapHosts(string $address, string $ip_address)
25
 * @method string _waitForTrafficToStop(integer $quiet_period, integer $timeout)
26
 * @method string _clearDnsCache()
27
 * @method string _rewriteUrl(string $match, string $replace)
28
 * @method string _retry(integer $retry_count)
29
 */
30
class BrowserMob extends Module
31
{
32
33
    protected $config = ['host', 'port', 'autostart', 'blacklist', 'whitelist', 'limits', 'timeouts', 'dns', 'retry', 'basicAuth', 'littleproxy'];
34
35
    protected $requiredFields = ['host'];
36
37
    protected $response;
38
39
    private $bmp;
40
41
    /**
42
     * @codeCoverageIgnore
43
     * @ignore Codeception specific
44
     */
45
    public function _initialize()
46
    {
47
        $host = $this->config['host'];
48
        if (isset($this->config['port'])) {
49
            $host = $host.':'.$this->config['port'];
50
        }
51
52
        // test if proxy is available
53
        if (static::__pingProxy($host)) {
54
            $this->bmp = new BMP($host);
55
        } else {
56
            throw new ModuleConfigException(__CLASS__, "Proxy '{$host}' cannot be reached");
57
        }
58
59
        // start a new BrowserMobProxy session
60
        if (isset($this->config['autostart'])) {
61
            if (true === (bool) $this->config['autostart']) {
62
                $this->openProxy();
63
            }
64
        }
65
    }
66
67
    protected static function __pingProxy($url)
68
    {
69
        try {
70
            $response = Requests::get('http://'.$url.'/proxy/');
71
        } catch (\Exception $e) {
72
            throw new ModuleException(__CLASS__, $e->getMessage());
73
        }
74
75
        return $response->success;
76
    }
77
78
    protected function __setProxyCapabilities($options)
79
    {
80
        foreach ($options as $config => $data) {
81
            if (false === empty($data)) {
82
                switch ((string) $config) {
83
                    case 'blacklist':
84
                        foreach ($data['patterns'] as $pattern) {
85
                            $this->_blacklist($pattern, $data['code']);
86
                        }
87
                        break;
88
                    case 'whitelist':
89
                        $patterns = implode(',', $data['patterns']);
90
                        $this->_whitelist($patterns, $data['code']);
91
                        break;
92
                    case 'limits':
93
                        $this->_limits($data);
94
                        break;
95
                    case 'timeouts':
96
                        $this->_timeouts($data);
97
                        break;
98
                    case 'dns':
99
                        foreach ($data as $entry) {
100
                            $this->_remapHosts($entry['domain'], $entry['ip']);
101
                        }
102
                        break;
103
                    case 'retry':
104
                        $this->_retry($data);
105
                        break;
106
                    case 'basicAuth':
107
                        foreach ($data as $entry) {
108
                            $this->_basicAuth($entry['domain'], $entry['options']);
109
                        }
110
                        break;
111
                    default:
112
                        // do nothing
113
                }
114
            }
115
        }
116
    }
117
118
    public function getProxyPort()
119
    {
120
        return $this->bmp->port;
121
    }
122
123
    public function openProxy($capabilities = null)
124
    {
125
        $this->_open();
126
        if (empty($capabilities)) {
127
            $capabilities = $this->config;
1 ignored issue
show
Coding Style introduced by
Consider using a different name than the parameter $capabilities. This often makes code more readable.
Loading history...
128
        }
129
        $this->__setProxyCapabilities($capabilities);
130
        return $this->getProxyPort();
131
    }
132
133
    public function closeProxy()
134
    {
135
        $this->_close();
136
    }
137
138
    public function startHar($label = '')
139
    {
140
        $this->_newHar($label);
141
        return $this->response->success;
142
    }
143
144
    public function addPage($label = '')
145
    {
146
        $this->_newPage($label);
147
        return $this->response->success;
148
    }
149
150
    public function getHar()
151
    {
152
        return $this->bmp->har;
153
    }
154
155
    public function setHeaders($headers)
156
    {
157
        $this->_headers($headers);
158
        return $this->response->success;
159
    }
160
161
    public function redirectUrl($match, $replace)
162
    {
163
        $this->_rewriteUrl($match, $replace);
164
        return $this->response->success;
165
    }
166
167
    public function filterRequest($script)
168
    {
169
        $this->_requestInterceptor($script);
170
        return $this->response->success;
171
    }
172
173
    public function filterResponse($script)
174
    {
175
        $this->_responseInterceptor($script);
176
        return $this->response->success;
177
    }
178
179
    // magic function that exposes BrowserMobProxy API pulic methods
180
    public function __call($name, $args)
181
    {
182
        // check if is a command call
183
        if (preg_match('/^_[A-z]+$/', $name)) {
184
            // extract standard method name
185
            $name = preg_filter('/_/', '', $name);
186
            // set call array for calling method
187
            $call = array($this->bmp, $name);
188
            // check if method is callable
189
            if (is_callable($call)) {
190
                $ret = call_user_func_array($call, $args);
191
                if (get_class($ret) === 'Requests_Response') {
192
                    $this->response = $ret;
193
                    if (false === $ret->success) {
194
                        throw new ModuleConfigException(__CLASS__, "Proxy response error '{$ret->status_code}' {$ret->body}");
195
                    }
196
                }
197
            } else {
198
                throw new RuntimeException("Method ${name} does not exist or is not callable");
199
            }
200
        } else {
201
            throw new RuntimeException("Method ${method} does not exist or is not callable");
202
        }
203
        $ret = (isset($ret)) ? $ret : null;
204
        return $ret;
205
    }
206
207
}
208