API client class v1.1.63

- changed references to *UbiOS* back to *UniFi OS*
- removed capitalization from all header strings (per RFC, header fields are case-insensitive: https://tools.ietf.org/html/rfc7230#section-3.2)
- removed charset parameter from headers (not required per RFC)
- added x-csrf-token header to all requests except GET when talking to UniFi OS-based controllers, thanks go to @paciks for raising #86
This commit is contained in:
malle-pietje
2021-01-06 17:03:21 +01:00
parent c82481a28a
commit a4998de3a9
2 changed files with 38 additions and 34 deletions

View File

@@ -1,6 +1,6 @@
## UniFi Controller API client class
A PHP class that provides access to Ubiquiti's [**UniFi Network Controller**](https://unifi-network.ui.com/) API, versions 4.X.X, 5.X.X and 6.0.X of the UniFi Network Controller software are supported (version 6.0.37 has been confirmed to work) as well as UbiOS-based controllers (version 5.12.59 has been confirmed to work). This class is used by our API browser tool which can be found [here](https://github.com/Art-of-WiFi/UniFi-API-browser).
A PHP class that provides access to Ubiquiti's [**UniFi Network Controller**](https://unifi-network.ui.com/) API, versions 4.X.X, 5.X.X and 6.0.X of the UniFi Network Controller software are supported (version 6.0.42 has been confirmed to work) as well as UniFi OS-based controllers (version 5.12.59 has been confirmed to work). This class is used by our API browser tool which can be found [here](https://github.com/Art-of-WiFi/UniFi-API-browser).
The package can be installed manually or by using composer/[packagist](https://packagist.org/packages/art-of-wifi/unifi-api-client) for easy inclusion in your projects.
@@ -11,11 +11,11 @@ The package can be installed manually or by using composer/[packagist](https://p
- you must use **local accounts**, not UniFi Cloud accounts, to access the UniFi Controller API through this class
## UbiOS Support
## UniFi OS Support
Support for UbiOS-based controllers (UniFi Dream Machine Pro) has been added as of version 1.1.47. The class automatically detects UbiOS devices and adjusts URLs and several functions/methods accordingly. If your own code applies strict validation of the URL that is passed to the constructor, please adapt your logic to allow URLs without a port suffix when dealing with a UbiOS-based controller.
Support for UniFi OS-based controllers (UniFi Dream Machine Pro) has been added as of version 1.1.47. The class automatically detects UniFi OS devices and adjusts URLs and several functions/methods accordingly. If your own code applies strict validation of the URL that is passed to the constructor, please adapt your logic to allow URLs without a port suffix when dealing with a UniFi OS-based controller.
Please test all methods you plan on using thoroughly before using the API Client with UbiOS devices in a production environment.
Please test all methods you plan on using thoroughly before using the API Client with UniFi OS devices in a production environment.
## Installation
@@ -300,7 +300,7 @@ This class is based on the initial work by the following developers:
and the API as published by Ubiquiti:
- https://dl.ui.com/unifi/5.12.35/unifi_sh_api
- https://dl.ui.com/unifi/6.0.41/unifi_sh_api
## Important Disclaimer

View File

@@ -10,9 +10,9 @@ namespace UniFi_API;
* and the API as published by Ubiquiti:
* https://www.ubnt.com/downloads/unifi/<UniFi controller version number>/unifi_sh_api
*
* @package UniFi Controller API client class
* @package UniFi_Controller_API_Client_Class
* @author Art of WiFi <info@artofwifi.net>
* @version 1.1.62
* @version Release: 1.1.63
* @license This class is subject to the MIT license that is bundled with this package in the file LICENSE.md
* @example This directory in the package repository contains a collection of examples:
* https://github.com/Art-of-WiFi/UniFi-API-client/tree/master/examples
@@ -31,7 +31,7 @@ class Client
protected $is_loggedin = false;
protected $is_unifi_os = false;
protected $exec_retries = 0;
protected $class_version = '1.1.62';
protected $class_version = '1.1.63';
private $cookies = '';
private $request_type = 'GET';
private $request_types_allowed = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];
@@ -160,7 +160,7 @@ class Client
$curl_options = [
CURLOPT_NOBODY => false,
CURLOPT_POSTFIELDS => json_encode(['username' => $this->user, 'password' => $this->password]),
CURLOPT_HTTPHEADER => ['content-type: application/json; charset=utf-8'],
CURLOPT_HTTPHEADER => ['content-type: application/json'],
CURLOPT_REFERER => $this->baseurl . '/login',
CURLOPT_URL => $this->baseurl . '/api/login'
];
@@ -260,7 +260,7 @@ class Client
/**
* constuct HTTP request headers as required
*/
$headers = ['Content-Length: 0'];
$headers = ['content-length: 0'];
$logout_path = '/logout';
if ($this->is_unifi_os) {
$logout_path = '/api/auth/logout';
@@ -3420,9 +3420,9 @@ class Client
}
/**
* Is current controller UnifiOS-based/UbiOS-based
* Is current controller UniFi OS-based
*
* @return bool whether current controller is UnifiOS-based/UbiOS-based
* @return bool whether current controller is UniFi OS-based
*/
public function get_is_unifi_os()
{
@@ -3599,7 +3599,7 @@ class Client
break;
default:
// we have an unknown error
$error = 'Unknown JSON error occured';
$error = 'Unknown JSON error occurred';
break;
}
@@ -3718,7 +3718,11 @@ class Client
return false;
}
/**
* assigne default values to these vars
*/
$json_payload = '';
$headers = [];
if ($this->is_unifi_os) {
$url = $this->baseurl . '/proxy/network' . $path;
@@ -3733,39 +3737,25 @@ class Client
CURLOPT_URL => $url
];
/**
* what we do when a payload is passed
*/
if (!is_null($payload)) {
$json_payload = json_encode($payload, JSON_UNESCAPED_SLASHES);
$curl_options[CURLOPT_POST] = true;
$curl_options[CURLOPT_POSTFIELDS] = $json_payload;
$headers = [
'Content-Type: application/json;charset=UTF-8',
'Content-Length: ' . strlen($json_payload)
'content-type: application/json',
'content-length: ' . strlen($json_payload)
];
if ($this->is_unifi_os) {
$csrf_token = $this->extract_csrf_token_from_cookie();
if ($csrf_token) {
$headers[] = 'x-csrf-token: ' . $csrf_token;
}
}
$curl_options[CURLOPT_HTTPHEADER] = $headers;
/**
* we shouldn't be using GET (the default request type) or DELETE when passing a payload,
* switch to POST instead
*/
switch ($this->request_type) {
case 'GET':
$this->request_type = 'POST';
break;
case 'DELETE':
$this->request_type = 'POST';
break;
case 'PUT':
$curl_options[CURLOPT_CUSTOMREQUEST] = 'PUT';
break;
if ($this->request_type === 'GET' || $this->request_type === 'DELETE') {
$this->request_type = 'POST';
}
}
@@ -3779,6 +3769,20 @@ class Client
case 'POST':
$curl_options[CURLOPT_CUSTOMREQUEST] = 'POST';
break;
case 'PUT':
$curl_options[CURLOPT_CUSTOMREQUEST] = 'PUT';
break;
}
if ($this->is_unifi_os && $this->request_type !== 'GET') {
$csrf_token = $this->extract_csrf_token_from_cookie();
if ($csrf_token) {
$headers[] = 'x-csrf-token: ' . $csrf_token;
}
}
if (count($headers) > 0) {
$curl_options[CURLOPT_HTTPHEADER] = $headers;
}
curl_setopt_array($ch, $curl_options);