Files
PVM/public_html/classes/Rest.class.php
2025-11-17 12:20:03 +01:00

498 lines
16 KiB
PHP

<?php
use Utility\Str;
class Rest {
const GET = "GET";
const POST = "POST";
const PUT = "PUT";
const PATCH = "PATCH";
const DELETE = "DELETE";
const TEXTPLAIN = "TEXT";
const APPLICATIONJSON = "JSON";
const FORM = "FORM";
const MULTIPART = "multipart";
public static $protocol = "http";
private $endPoint = null;
private $contentType = null;
private $method = null;
private $service = null;
private $serviceRootPath = null;
private $authUsername = null;
private $authPassword = null;
private $urlData = array();
private $headers = array();
private $body = array();
private $privateKey = null;
private $publicKey = null;
private $isDownload = false;
private $isDirectDownload = false;
private $downloadType = "inline";
private $profileDb = null;
private $timeout = 0;
private $isDirect = false;
// <editor-fold desc="SETTERS" defaultstate="collapsed">
public function post() {
return $this->method(self::POST);
}
public function get() {
return $this->method(self::GET);
}
public function asText() {
return $this->contentType(self::TEXTPLAIN);
}
public function asJson() {
return $this->contentType(self::APPLICATIONJSON);
}
public function asForm() {
return $this->contentType(self::FORM);
}
public function header($key, $value) {
$this->headers[$key] = $value;
return $this;
}
public function headers($array) {
$this->headers = array_merge($this->headers, $array);
return $this;
}
public function urlData($value) {
$this->urlData = $value;
return $this;
}
public function body($value) {
$this->body = $value;
return $this;
}
public function contentType($value) {
$this->contentType = $value;
return $this;
}
public function endPoint($value) {
$this->endPoint = $value;
return $this;
}
/**
* @param null $profileDb
*/
public function setProfileDb($profileDb) {
$this->profileDb = $profileDb;
return $this;
}
/**
* @return null
*/
public function getProfileDb() {
return $this->profileDb;
}
public function method($value) {
$this->method = $value;
return $this;
}
public function serviceRootPath($value) {
$this->serviceRootPath = $value;
return $this;
}
public function service($value) {
$this->service = $value;
return $this;
}
public function authUsername($value) {
$this->authUsername = $value;
return $this->header("username", $value);
/********* it memorizes in the object headers the key "username" with the value "$value" ***************/
}
public function authPassword($value) {
$this->authPassword = $value;
return $this->header("password", $value);
}
public function privateKey($value) {
$this->privateKey = $value;
return $this;
}
public function publicKey($value) {
$this->publicKey = $value;
return $this;
}
public function timeout($seconds) {
$this->timeout = $seconds;
return $this;
}
// </editor-fold>
// <editor-fold desc="GETTERS" defaultstate="collapsed">
public function get_endPoint() {
$endPoint = null;
if (!is_null($this->endPoint)) {
$endPoint = $this->endPoint;
} else {
if (file_exists("classes/Restful.config.json")) {
$restConfig = @json_decode(file_get_contents("classes/Restful.config.json"), true);
if (!is_null($restConfig) && isset($restConfig["endPoint"])) {
$endPoint = Controller::endPointParsed($restConfig["endPoint"]) . "/";
}
}
if (is_null($endPoint)) {
// if (PVM::isDevClient()) {
// $endPoint = Controller::endPointParsed("localhost:8080") . "/";
// } else {
$endPoint = Config::get_endPoint($this->profileDb) . "/";
// }
}
}
if (!is_null($this->serviceRootPath)) {
$endPoint .= Str::endsWith($endPoint, $this->serviceRootPath) ? "" : $this->serviceRootPath;
}
return $endPoint;
}
public static function get_endPointRemote() {
$endPoint = null;
if (file_exists("classes/Restful.config.json")) {
$restConfig = @json_decode(file_get_contents("classes/Restful.config.json"), true);
if (!is_null($restConfig) && isset($restConfig["endPointRemote"])) {
$endPoint = Controller::endPointParsed($restConfig["endPointRemote"]) . "/";
}
}
if (is_null($endPoint)) {
if (PVM::isDevClient()) {
$endPoint = Controller::endPointParsed(array_get($_ENV, "SERVICES_BASE_URL")) . "/";
} else {
$endPoint = Controller::endPointParsed(Config::get_endPointRemote()) . "/";
}
}
return $endPoint;
}
private static function get_profileDb() {
return Config::get_dbNameWeb();
}
/******************************* SERVICE URL CONSTRUCTION **********************************************************/
private function get_url() {
$url = $this->get_endPoint() . $this->service;
$urlData = $this->urlData;
if (!array_key_exists("profileDb", $urlData)) {
$profileDb = self::get_profileDb();
if (!is_null($profileDb)) {
$urlData["profileDb"] = $profileDb;
}
}
if (count($urlData) > 0) {
$url = sprintf("%s?%s", $url, preg_replace('/%5B\d+%5D/', '%5B%5D', http_build_query($urlData)));
}
return $url;
}
private function get_authCredentials() {
return (!is_null($this->authUsername)
&& !is_null($this->authPassword)) ? array(
"username" => $this->authUsername, "password" => $this->authPassword
) : null;
}
// </editor-fold>
/************************************ CONNECTION BETWEEN PHP AND REST APIs *****************************************/
public function send() {
$Ret = new Ret;
$ret = array("headers" => null, "url" => null, "payload" => null, "http_code" => null, "body" => null);
try {
$url = $this->get_url();
/************************ creation of REQUEST OBJ ************************/
switch ($this->method) {
case self::POST:
$req = \Httpful\Request::post($url);
break;
case self::PUT:
$req = \Httpful\Request::put($url);
break;
case self::PATCH:
$req = \Httpful\Request::patch($url);
break;
case self::DELETE:
$req = \Httpful\Request::delete($url);
break;
default:
$req = \Httpful\Request::get($url);
}
$credentials = $this->get_authCredentials();
if (!is_null($credentials)) {
$req->authenticateWith($credentials["username"], $credentials["password"]);
}
foreach ($this->headers as $k => $v) {
$req->addHeader($k, $v);
}
/***************** here the body of Rest is passed to Request *******************/
if (!is_null($this->publicKey)) {
$req->body(self::encryptRsa(json_encode($this->body), $this->publicKey));
} else {
$req->body($this->body);
}
if ($this->contentType == self::APPLICATIONJSON) {
$req->sendsJson();
} else if ($this->contentType == self::FORM) {
$req->sendsType(Httpful\Mime::FORM);
} else if ($this->contentType == self::MULTIPART) {
$req->sendsType(Httpful\Mime::UPLOAD);
}
if ($this->timeout > 0) {
$req->timeoutIn($this->timeout);
}
$ret["headers"] = $req->headers;
/************************** if there's password, overwrites it with asterisks in ret *************** */
if (isset($ret["headers"]["password"])) {
$ret["headers"]["password"] = str_pad("", strlen($ret["headers"]["password"]), "*");
/****** last option: STR_PAD_RIGHT default */
}
$ret["payload"] = $req->payload;
$ret["url"] = $url;
/**************************** FINALLY SEND *******************************/
$result = @$req->send();
/************* no parameters passed!!! ******************/
if ($this->isDirect()) {
$Ret->set_data($result)->displayData();
}
$httpCode = $result->code;
$rawHeaders = $result->raw_headers;
$ret["http_code"] = $httpCode;
$ret["body"] = $result->raw_body;
$Ret->set_number($httpCode);
$rawResponse = $result->raw_body;
if (!is_null($this->privateKey)) {
$rawResponse = self::decryptRsa($rawResponse, $this->privateKey);
}
$retData = $this->isDownload() ? null : json_decode($rawResponse, true);
if (!isset($retData[0])) {
$retData = array($retData);
}
if ($httpCode == 200) {
if ($this->isDownload()) {
header("Cache-Control: no-cache");
header("Cache-Control: private", false); // required for certain browsers
$headers = explode("\r\n", $rawHeaders);
$headers = array_filter($headers, function ($header) {
return
strpos($header, "Content-Disposition:") === 0
|| strpos($header, "Content-Type:") === 0
|| strpos($header, "Content-Length:") === 0;
});
$contentDisposition = from($headers)->where(function ($header) {
return strpos($header, "Content-Disposition:") === 0;
})->firstOrDefault();
if ($this->isDirectDownload) {
header("Cache-Control: private, max-age=86400, must-revalidate");
header("Cache-Control: private", false);
foreach ($headers as $header) {
header($header);
}
if ($this->downloadType === "inline") {
$fileName = strpos($contentDisposition, "filename");
if ($fileName) {
header("Content-Disposition: inline; "
. substr($contentDisposition, $fileName, strlen($contentDisposition)));
} else {
header("Content-Disposition: inline");
}
}
}
$retData = $rawResponse;
$Ret->set_data($retData);
} else {
if (isset($retData[0]["esito"])) {
if ($retData[0]["esito"] == 1) {
$Ret->set_data($retData);
} else {
if ($retData) {
$Ret->set_data($retData);
}
if (isset($retData[0]["errorMessage"])) {
$Ret->set_error($retData[0]["errorMessage"]);
} else {
$Ret->set_errorCode(ErrorHandler::EMSNOMESSAGE, $this->service);
}
}
} else {
$Ret->set_errorCode(ErrorHandler::EMSPARSE, $this->service);
$suffixPath = "EMSPARSE-" . User::get_current_username();
$logPath = Utility::write_log("Parse error rest call: " . $result->raw_body, $suffixPath);
if ($logPath !== false && PVM::isDebugEnv()) {
$Ret->append_errorText("<br/><span class='small text-monospace'>Consulta <a href='{$logPath}' download>"
. basename($logPath) . "</a></span>");
}
}
}
} else if ($httpCode == 400) {
$errorLog = "400";
$Ret->set_errorCode(ErrorHandler::EMSHTTP400, $this->service, array_get($retData, "0.errorMessage"));
} else if ($httpCode == 401) {
$errorLog = "401";
$Ret->set_errorCode(ErrorHandler::EMSHTTP401, $this->service, array_get($retData, "0.errorMessage"));
} else if ($httpCode == 550) {
$errorLog = "550";
$Ret->set_errorCode(ErrorHandler::EMSHTTP550, $this->service);
} else if ($httpCode == 551) {
$errorLog = "551";
$Ret->set_errorCode(ErrorHandler::EMSHTTP551, $this->service);
} else {
$errorLog = $httpCode;
$Ret->set_errorCode(ErrorHandler::EMSHTTP, $httpCode, $rawHeaders, $this->service);
}
} catch (Httpful\Exception\ConnectionErrorException $e) {
$errorLog = "EMSCONNECT";
$Ret
->set_errorCode(ErrorHandler::EMSCONNECT, $this->service)
->append_errorText(" su <span class='text-monospace'>" . $this->get_endPoint() . "</span>")
->set_error($e->getMessage());
} catch (Exception $e) {
$errorLog = "restCatchError";
$Ret->set_error($e->getMessage());
}
if (!$Ret->is_OK() && isset($errorLog) && !PVM::isDevClient()) { // SE NON VA A BUON FINE SCRIVE SEMPRE NEL LOG
if (isset($this->body)) {
$fileName = "Payload_" . $errorLog . "_" . blankIfNull($this->service) . "_"
. User::get_current_username();
@Utility::write_log($this->body, $fileName);
}
$suffixPath = isset($suffixPath) ? $suffixPath : $errorLog . "_" . blankIfNull($this->service) . "_"
. User::get_current_username();
@Utility::write_log($ret, $suffixPath);
}
return $Ret;
}
private static function encryptRsa($data, $pubKey) {
$rsa = new Crypt_RSA;
$rsa->loadKey($pubKey);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
return base64_encode($rsa->encrypt($data));
}
private static function decryptRsa($data, $privKey) {
$rsa = new Crypt_RSA;
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$ciphertext = base64_decode($data);
$rsa->loadKey($privKey);
return $rsa->decrypt($ciphertext);
}
/**
* @return bool
*/
public function isDownload() {
return $this->isDownload;
}
/**
* @param bool $isDownload
* @return Rest
*/
public function setIsDownload($isDownload) {
$this->isDownload = $isDownload;
return $this;
}
/**
* @return bool
*/
public function isDirectDownload() {
return $this->isDirectDownload;
}
/**
* @param bool $isDownload
* @return Rest
*/
public function setIsDirectDownload($isDirectDownload) {
$this->isDirectDownload = $isDirectDownload;
return $this;
}
public function getDownloadType() {
return $this->downloadType;
}
public function setDownloadType($downloadType) {
$this->downloadType = $downloadType;
return $this;
}
/**
* @return bool
*/
public function isDirect() {
return $this->isDirect;
}
/**
* @param bool $isDirect
* @return Rest
*/
public function setIsDirect($isDirect) {
$this->isDirect = $isDirect;
return $this;
}
}