Merge "Fix Postgres support"
[lhc/web/wiklou.git] / includes / http / Http.php
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21 use MediaWiki\Logger\LoggerFactory;
22
23 /**
24 * Various HTTP related functions
25 * @ingroup HTTP
26 */
27 class Http {
28 static public $httpEngine = false;
29
30 /**
31 * Perform an HTTP request
32 *
33 * @param string $method HTTP method. Usually GET/POST
34 * @param string $url Full URL to act on. If protocol-relative, will be expanded to an http:// URL
35 * @param array $options Options to pass to MWHttpRequest object.
36 * Possible keys for the array:
37 * - timeout Timeout length in seconds
38 * - connectTimeout Timeout for connection, in seconds (curl only)
39 * - postData An array of key-value pairs or a url-encoded form data
40 * - proxy The proxy to use.
41 * Otherwise it will use $wgHTTPProxy (if set)
42 * Otherwise it will use the environment variable "http_proxy" (if set)
43 * - noProxy Don't use any proxy at all. Takes precedence over proxy value(s).
44 * - sslVerifyHost Verify hostname against certificate
45 * - sslVerifyCert Verify SSL certificate
46 * - caInfo Provide CA information
47 * - maxRedirects Maximum number of redirects to follow (defaults to 5)
48 * - followRedirects Whether to follow redirects (defaults to false).
49 * Note: this should only be used when the target URL is trusted,
50 * to avoid attacks on intranet services accessible by HTTP.
51 * - userAgent A user agent, if you want to override the default
52 * MediaWiki/$wgVersion
53 * - logger A \Psr\Logger\LoggerInterface instance for debug logging
54 * - username Username for HTTP Basic Authentication
55 * - password Password for HTTP Basic Authentication
56 * - originalRequest Information about the original request (as a WebRequest object or
57 * an associative array with 'ip' and 'userAgent').
58 * @param string $caller The method making this request, for profiling
59 * @return string|bool (bool)false on failure or a string on success
60 */
61 public static function request( $method, $url, $options = [], $caller = __METHOD__ ) {
62 $logger = LoggerFactory::getInstance( 'http' );
63 $logger->debug( "$method: $url" );
64
65 $options['method'] = strtoupper( $method );
66
67 if ( !isset( $options['timeout'] ) ) {
68 $options['timeout'] = 'default';
69 }
70 if ( !isset( $options['connectTimeout'] ) ) {
71 $options['connectTimeout'] = 'default';
72 }
73
74 $req = MWHttpRequest::factory( $url, $options, $caller );
75 $status = $req->execute();
76
77 if ( $status->isOK() ) {
78 return $req->getContent();
79 } else {
80 $errors = $status->getErrorsByType( 'error' );
81 $logger->warning( Status::wrap( $status )->getWikiText( false, false, 'en' ),
82 [ 'error' => $errors, 'caller' => $caller, 'content' => $req->getContent() ] );
83 return false;
84 }
85 }
86
87 /**
88 * Simple wrapper for Http::request( 'GET' )
89 * @see Http::request()
90 * @since 1.25 Second parameter $timeout removed. Second parameter
91 * is now $options which can be given a 'timeout'
92 *
93 * @param string $url
94 * @param array $options
95 * @param string $caller The method making this request, for profiling
96 * @return string|bool false on error
97 */
98 public static function get( $url, $options = [], $caller = __METHOD__ ) {
99 $args = func_get_args();
100 if ( isset( $args[1] ) && ( is_string( $args[1] ) || is_numeric( $args[1] ) ) ) {
101 // Second was used to be the timeout
102 // And third parameter used to be $options
103 wfWarn( "Second parameter should not be a timeout.", 2 );
104 $options = isset( $args[2] ) && is_array( $args[2] ) ?
105 $args[2] : [];
106 $options['timeout'] = $args[1];
107 $caller = __METHOD__;
108 }
109 return Http::request( 'GET', $url, $options, $caller );
110 }
111
112 /**
113 * Simple wrapper for Http::request( 'POST' )
114 * @see Http::request()
115 *
116 * @param string $url
117 * @param array $options
118 * @param string $caller The method making this request, for profiling
119 * @return string|bool false on error
120 */
121 public static function post( $url, $options = [], $caller = __METHOD__ ) {
122 return Http::request( 'POST', $url, $options, $caller );
123 }
124
125 /**
126 * A standard user-agent we can use for external requests.
127 * @return string
128 */
129 public static function userAgent() {
130 global $wgVersion;
131 return "MediaWiki/$wgVersion";
132 }
133
134 /**
135 * Checks that the given URI is a valid one. Hardcoding the
136 * protocols, because we only want protocols that both cURL
137 * and php support.
138 *
139 * file:// should not be allowed here for security purpose (r67684)
140 *
141 * @todo FIXME this is wildly inaccurate and fails to actually check most stuff
142 *
143 * @param string $uri URI to check for validity
144 * @return bool
145 */
146 public static function isValidURI( $uri ) {
147 return (bool)preg_match(
148 '/^https?:\/\/[^\/\s]\S*$/D',
149 $uri
150 );
151 }
152
153 /**
154 * Gets the relevant proxy from $wgHTTPProxy
155 *
156 * @return mixed The proxy address or an empty string if not set.
157 */
158 public static function getProxy() {
159 global $wgHTTPProxy;
160
161 if ( $wgHTTPProxy ) {
162 return $wgHTTPProxy;
163 }
164
165 return "";
166 }
167
168 /**
169 * Get a configured MultiHttpClient
170 * @param array $options
171 */
172 public static function createMultiClient( $options = [] ) {
173 global $wgHTTPConnectTimeout, $wgHTTPTimeout, $wgHTTPProxy;
174
175 return new MultiHttpClient( $options + [
176 'connTimeout' => $wgHTTPConnectTimeout,
177 'reqTimeout' => $wgHTTPTimeout,
178 'userAgent' => self::userAgent(),
179 'proxy' => $wgHTTPProxy,
180 'logger' => LoggerFactory::getInstance( 'http' )
181 ] );
182 }
183 }