The Invision Community framework provides a powerful helper class to work with URLs, including parsing URLs and making requests to (and reading responses from) URLs. The software automatically uses cURL when available, falling back to standard sockets if not (this behavior can also be overridden by constants if an environment wishes to force cURL or sockets, specifically).
Working with URLs
The \IPS\Http\Url class is used to work with URLs, and two helper methods form the primary interface to create a URL object with this class:
- internal(): Use this method when creating an internal URL, such as a URL to a forum or topic. The method handles automatically creating friendly URLs when configured to do so.
- external(): Pass any full URL to this method to create a URL object out of the URL string.
// Create a URL to topic ID 1 $url = \IPS\Http\Url::internal( 'app=forums&module=forums&controller=topic&id=1', 'front', 'forums_topic', array( 'topic-friendly-slug' ) ); $url = \IPS\Http\Url::external( 'https://www.google.com' ); // Create a URL object for a standard URL string
The internal method accepts the following parameters:
- The URL query string
- The 'base' ('front' or 'admin', depending upon whether the URL is to a page in the AdminCP or not)
- The SEO template, if applicable
- An array of SEO slugs if the template calls for one
- A PROTOCOL_* constant from \IPS\Http\Url to override whether an http or https URL should be generated. You can usually omit this parameter and let the software determine the right protocol to use automatically.
The external method simply accepts a URL string.
If you are unsure if the URL object you are creating is internal or external, you can alternatively use the createFromString() method (passing the full URL as you would with the external() method), however note that this method is somewhat performance-intensive and the directly internal() and external() methods are preferred. The first parameter for this method is the URL, the second parameter is a boolean flag indicating if the URL may be a friendly internal URL, and the third and final parameter is a boolean flag indicating if you wish to automatically encode any components that are invalid instead of throwing an error (defaulting to FALSE - set this to TRUE if the URL is user-supplied and should not throw an error).
You can make adjustments to the URL after creating the URL object by calling various methods.
- setScheme(): You can pass the scheme in (i.e. http or https), or pass in NULL to use a protocol-relative scheme (i.e. no scheme)
- setHost(): Accepts a full host name
- setPath(): Accepts a full valid path
- setQueryString(): Accepts a query string key as the first parameter and its value as the second parameter OR an array of key => value pairs as the first parameter
- setFragment(): Accepts a fragment
- stripQueryString(): Accepts a query string key or an array of query string keys and removes those query string parameters (if present) from the URL
When you wish to output the URL, you can cast the \IPS\Http\Url object as a string
print (string) $urlObject;
The class has a few additional properties and methods you may wish to reference or call, outlined below:
- isInternal: This property denotes if the URL is internal or not
- isFriendly: This property denotes if the URL is a friendly (internal) URL or not
- queryString: This property is an array of key => value query string parameters in the URL
- hiddenQueryString: This property is an array of key => value query string parameters that would have been present if the URL were not a friendly URL. For instance, if you create an internal friendly URL object, this property will contain the associated query string parameters that are not shown (because a friendly URL is used)
- csrf(): Call this method to add the current viewing user's CSRF key to the URL as a query string argument. This is then later checked in controllers to prevent CSRF-style attacks. If you have a state-changing request that does not use the \IPS\Helpers\Form class, you should typically check the CSRF key.
- (static) seoTitle(): You can call this method to create a valid friendly URL slug. Typically this is done when content is submitted and the URL slug is stored for later reference, however you can also call this method on the fly if needed.
Making requests
Once you have created an \IPS\Http\Url object, you can make requests to it. To do this, you first call request() against the URL object.
/** * Make a HTTP Request * * @param int|null $timeout Timeout * @param string $httpVersion HTTP Version * @param bool|int $followRedirects Automatically follow redirects? If a number is provided, will follow up to that number of redirects * @return \IPS\Http\Request */ public function request( $timeout=null, $httpVersion=null, $followRedirects=5 )
This returns an \IPS\Http\Request object. From here there are some methods you can call before executing the request:
- login(): Accepts a username as the first parameter and a password as the second parameter, and performs a basic authorization request against the URL.
- setHeaders(): Accepts an array of key => value pairs of headers that should be included with the request.
- sslCheck(): Accepts a boolean true or false as the only parameter, signaling whether SSL certificates should be validated or not. In most cases, this should be left default (true), unless you are aware that the SSL URL you are making a request against has an invalid certificate.
- forceTls(): Forces TLS for the request. This is primarily used with some payment gateways that enforce TLS requests.
Afterwards, you can now make the request. To do so, you call the request method that you wish to perform (e.g. to perform a GET request you call get() and to perform a PUT request you call put()), passing along any parameters that should be included with the request (for POST and PUT requests).
$request = \IPS\Http\Url::external( "http://someurl.com" )->request()->get();
This returns an \IPS\Http\Response object, which you can now inspect and manipulate as needed. Firstly, there are several useful properties you may need to reference:
- httpResponseVersion: This is the HTTP version of the response (1.0 or 1.1, typically)
- httpResponseCode: This is the HTTP response code. You may need to verify that a valid response code (i.e. 200) was returned after making a request.
- httpResponseText: This is the HTTP response text. For a 200 request, for instance, this will be "OK".
- httpHeaders: This will be an array containing all HTTP headers in the response as key => value pairs
- cookies: This will be an array of all Set-Cookie headers as key => value pairs.
- content: This is the body of the response.
Casting the response as a string returns the content property noted above.
There are some methods in the \IPS\Http\Response class that you can leverage to make working with certain common responses easier.
- decodeJson(): Calling this method will run the response through json_decode before returning it. If the response is not valid JSON, a RuntimeException will be thrown.
- decodeXml(): Calling this method will parse the response as XML, throwing a RuntimeException if the response is not valid XML.
It is additionally worth noting that if the request fails for some reason (for instance, a time out connecting to the remote server), an \IPS\Http\Request\Exception exception will be thrown. To that end, you must wrap requests in a try/catch block.
// Create a URL object $url = \IPS\Http\Url::external( "http://someurl.com" )->setQueryString( 'key', 'value' ); // Now fetch it and decode the JSON try { $response = $url->request()->get()->decodeJson(); } catch( \IPS\Http\Request\Exception $e ) { die( "There was a problem fetching the request" ); } catch( \RuntimeException $e ) { die( "The response was not valid JSON" ); } var_dump( $response ); exit;
Report Document