Skip to content

Commit

Permalink
API client class v1.1.63
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
malle-pietje committed Jan 6, 2021
1 parent c82481a commit a4998de
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 34 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down
62 changes: 33 additions & 29 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
* 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 <[email protected]>
* @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
Expand All @@ -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'];
Expand Down Expand Up @@ -160,7 +160,7 @@ public function login()
$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'
];
Expand Down Expand Up @@ -260,7 +260,7 @@ public function logout()
/**
* 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';
Expand Down Expand Up @@ -3420,9 +3420,9 @@ public function set_ssl_verify_host($ssl_verify_host)
}

/**
* 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()
{
Expand Down Expand Up @@ -3599,7 +3599,7 @@ private function catch_json_last_error()
break;
default:
// we have an unknown error
$error = 'Unknown JSON error occured';
$error = 'Unknown JSON error occurred';
break;
}

Expand Down Expand Up @@ -3718,7 +3718,11 @@ protected function exec_curl($path, $payload = null)
return false;
}

/**
* assigne default values to these vars
*/
$json_payload = '';
$headers = [];

if ($this->is_unifi_os) {
$url = $this->baseurl . '/proxy/network' . $path;
Expand All @@ -3733,39 +3737,25 @@ protected function exec_curl($path, $payload = null)
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';
}
}

Expand All @@ -3779,6 +3769,20 @@ protected function exec_curl($path, $payload = null)
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);
Expand Down

0 comments on commit a4998de

Please sign in to comment.