GancioF2F/lib/curl.php

112 lines
4.2 KiB
PHP

<?php
/*
date: Sun, 20 Oct 2024 17:29:05 GMT
x-ratelimit-limit: 300
x-ratelimit-remaining: 299
x-ratelimit-reset: 2024-10-20T17:30:00.196177Z
*/
/*
To use the rate limit check function, you have to pass a unique "$napid" for
every "$url" that shares the same rate limit, and define a "cknap" function
like this:
---
function cknap($napid) {
global $naps;
$now=time();
if (isset($naps[$napid]) && $naps[$napid]>$now) {
echo "Info: reached rate limit on «{$napid}»; sleeping until ".date('c',$naps[$napid]).' ...';
sleep($naps[$napid]-$now);
echo "\n";
$naps[$napid]=0;
}
}
---
Example usage:
---
$postData=['file'=>new CURLStringFile($file['content'],$file['name'],$file['type']), 'description'=>$file['description'];
$url="https://{$conf['fedi_hostname']}/api/v2/media";
$res=curl($url,'/api/v2/media',["Authorization: Bearer {$conf['fedi_token']}", 'Accept: application/json'],$postData);
if ($res['content']===false) {
echo "Warning: could not connect to «{$url}» (error: «{$res['error']}»).\n";
} elseif (is_null($res['content']=@json_decode($res['content'],true))) {
echo "Warning: «{$url}» did not return valid JSON.\n";
} elseif ($res['httpcode']!='200' && $res['httpcode']!='202') {
(isset($res['content']['error'])) ? $buff=" (error: «{$res['content']['error']}»)" : $buff='';
echo "Warning: «{$url}» returned http code «{$res['httpcode']}»{$buff}.\n";
} elseif (!isset($res['content']['id'])) {
echo "Warning: no «id» in JSON from «{$url}».\n";
} else {
$id=$res['content']['id'];
[...]
}
---
*/
function curl($url,$napid=null,$headers=null,$postdata=null,$conntimeout=null,$functimeout=null,$proxy=null) {
if (!is_null($napid)) cknap($napid);
if (is_null($conntimeout)) $conntimeout=5;
if (is_null($functimeout)) $functimeout=20;
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_FAILONERROR,false);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$conntimeout);
curl_setopt($ch,CURLOPT_TIMEOUT,$functimeout);
curl_setopt($ch,CURLOPT_HEADER,true);
// example $headers: ['Content-type: text/plain', 'Content-length: 100']
if (is_array($headers)) curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_ENCODING,'');
curl_setopt($ch,CURLOPT_USERAGENT,'curl/1.0');
// curl automatically uses a "Content-Type" of "multipart/form-data" if $postdata is an array, of "application/x-www-form-urlencoded" if it's a string
if (!is_null($postdata)) curl_setopt($ch,CURLOPT_POSTFIELDS,$postdata);
if (!is_null($proxy)) {
curl_setopt($ch,CURLOPT_PROXY,$proxy);
curl_setopt($ch,CURLOPT_PROXYTYPE,CURLPROXY_SOCKS5);
}
$gheaders=null;
$httpcode=null;
$error=false;
$res=curl_exec($ch);
if ($res!==false) {
$now=time();
$gheaders_sz=curl_getinfo($ch,CURLINFO_HEADER_SIZE);
$gheaders=substr($res,0,$gheaders_sz-4);// "-4" accounts for the 2 "\r\n" that separates headers from body
// echo "{$gheaders}\n";
$gheaders=explode("\r\n",$gheaders);
// the line below is needed to discard from the top of the headers possible "HTTP/(version) 100 Continue" and the empty lines that may follow
while (trim($gheaders[0])=='' || preg_match('#^HTTP/\d+\.\d+\s+100\s+#',$gheaders[0])===1) array_shift($gheaders);
$res=substr($res,$gheaders_sz);
$httpcode=preg_replace('#^\S+\s+(\d+).*$#','$1',$gheaders[0]);
if (!is_null($napid)) {
global $naps;
foreach ($gheaders as $header) {
if (preg_match('#^date: (.*)$#i',$header,$matches)===1) {
$sdate=@strtotime($matches[1]);
if ($sdate===false) break;
} elseif (preg_match('#^x-ratelimit-remaining: (\d+)$#i',$header,$matches)===1) {
$rlrem=$matches[1]+0;
// echo "Ratelimit-remaining: {$rlrem}\n";
} elseif (preg_match('#^x-ratelimit-reset: (.*)$#i',$header,$matches)===1) {
$rlres=@strtotime($matches[1]);
if ($rlres===false) break;
}
if (isset($sdate) && isset($rlrem) && isset($rlres)) {
// echo "date: {$sdate}; rem: {$rlrem}; res: {$rlres}.\n";
if ($rlrem==0) $naps[$napid]=$now+$rlres-$sdate+1;
break;
}
}
}
} else {
$error=curl_errno($ch).': '.trim(curl_error($ch));
}
curl_close($ch);
return ['content'=>$res,'httpcode'=>$httpcode,'headers'=>$gheaders,'error'=>$error];
}
?>