Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
83.87% |
26 / 31 |
|
66.67% |
4 / 6 |
CRAP | |
0.00% |
0 / 1 |
HttpRequestExecutor | |
83.87% |
26 / 31 |
|
66.67% |
4 / 6 |
12.60 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
setLogger | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
execute | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
executePost | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
executeAndSave | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
executeHttpRequest | |
90.48% |
19 / 21 |
|
0.00% |
0 / 1 |
6.03 | |||
buildUserAgentString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace FileImporter\Services\Http; |
4 | |
5 | use FileImporter\Exceptions\HttpRequestException; |
6 | use MediaWiki\Http\HttpRequestFactory; |
7 | use MWHttpRequest; |
8 | use Psr\Log\LoggerAwareInterface; |
9 | use Psr\Log\LoggerInterface; |
10 | use Psr\Log\NullLogger; |
11 | |
12 | /** |
13 | * @license GPL-2.0-or-later |
14 | * @author Addshore |
15 | */ |
16 | class HttpRequestExecutor implements LoggerAwareInterface { |
17 | |
18 | private HttpRequestFactory $httpRequestFactory; |
19 | private LoggerInterface $logger; |
20 | private int $maxFileSize; |
21 | private array $httpOptions; |
22 | |
23 | /** |
24 | * @param HttpRequestFactory $httpRequestFactory |
25 | * @param array $httpOptions in the following format: |
26 | * [ |
27 | * 'originalRequest' => WebRequest|string[] When in array form, it's expected to have the |
28 | * keys 'ip' and 'userAgent', {@see MWHttpRequest::setOriginalRequest}, |
29 | * 'proxy' => string|false, |
30 | * 'timeout' => int|false Timeout of HTTP requests in seconds, false for default, |
31 | * ] |
32 | * @param int $maxFileSize in bytes |
33 | */ |
34 | public function __construct( |
35 | HttpRequestFactory $httpRequestFactory, |
36 | array $httpOptions, |
37 | int $maxFileSize |
38 | ) { |
39 | $this->httpRequestFactory = $httpRequestFactory; |
40 | $this->logger = new NullLogger(); |
41 | $this->maxFileSize = $maxFileSize; |
42 | $this->httpOptions = $httpOptions; |
43 | } |
44 | |
45 | /** |
46 | * @codeCoverageIgnore |
47 | */ |
48 | public function setLogger( LoggerInterface $logger ): void { |
49 | $this->logger = $logger; |
50 | } |
51 | |
52 | /** |
53 | * @throws HttpRequestException |
54 | */ |
55 | public function execute( string $url, array $parameters = [] ): MWHttpRequest { |
56 | return $this->executeHttpRequest( wfAppendQuery( $url, $parameters ) ); |
57 | } |
58 | |
59 | public function executePost( string $url, array $postData ): MWHttpRequest { |
60 | return $this->executeHttpRequest( $url, null, $postData ); |
61 | } |
62 | |
63 | /** |
64 | * @throws HttpRequestException |
65 | */ |
66 | public function executeAndSave( string $url, string $filePath ): MWHttpRequest { |
67 | $chunkSaver = new FileChunkSaver( $filePath, $this->maxFileSize ); |
68 | $chunkSaver->setLogger( $this->logger ); |
69 | return $this->executeHttpRequest( $url, [ $chunkSaver, 'saveFileChunk' ] ); |
70 | } |
71 | |
72 | /** |
73 | * @throws HttpRequestException |
74 | */ |
75 | private function executeHttpRequest( |
76 | string $url, |
77 | ?callable $callback = null, |
78 | ?array $postData = null |
79 | ): MWHttpRequest { |
80 | $options = [ |
81 | 'logger' => $this->logger, |
82 | 'followRedirects' => true, |
83 | ]; |
84 | if ( isset( $this->httpOptions['originalRequest'] ) ) { |
85 | $options['originalRequest'] = $this->httpOptions['originalRequest']; |
86 | } |
87 | if ( !empty( $this->httpOptions['proxy'] ) ) { |
88 | $options['proxy'] = $this->httpOptions['proxy']; |
89 | } |
90 | $timeout = $this->httpOptions['timeout'] ?? false; |
91 | if ( $timeout !== false ) { |
92 | $options['timeout'] = $timeout; |
93 | } |
94 | if ( $postData !== null ) { |
95 | $options['method'] = 'POST'; |
96 | $options['postData'] = $postData; |
97 | } |
98 | $options['userAgent'] = $this->buildUserAgentString(); |
99 | |
100 | /** @var MWHttpRequest $request */ |
101 | $request = $this->httpRequestFactory->create( $url, $options, __METHOD__ ); |
102 | |
103 | $request->setCallback( $callback ); |
104 | |
105 | $status = $request->execute(); |
106 | if ( !$status->isOK() ) { |
107 | throw new HttpRequestException( $status, $request ); |
108 | } |
109 | |
110 | return $request; |
111 | } |
112 | |
113 | private function buildUserAgentString(): string { |
114 | // TODO: Pull URL and version from ExtensionRegistry. |
115 | return 'mw-ext-FileImporter/* (https://www.mediawiki.org/wiki/Extension:FileImporter)'; |
116 | } |
117 | |
118 | } |