123 lines
4.3 KiB
PHP
123 lines
4.3 KiB
PHP
<?php
|
|
|
|
/*
|
|
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_FOLLOWLOCATION,true);
|
|
curl_setopt($ch,CURLOPT_MAXREDIRS,10);
|
|
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);
|
|
// code until "---" is to find the beginning of "real headers", that is: after all the possible "100" or "302" http headers, or the likes
|
|
$count=count($gheaders)-1;
|
|
$rhi=null;
|
|
for ($i=$count; $i>-1; $i--) {
|
|
if (trim($gheaders[$i])=='') {
|
|
$rhi=$i+1;
|
|
break;
|
|
}
|
|
}
|
|
if (!is_null($rhi)) $gheaders=array_slice($gheaders,$rhi);
|
|
// ---
|
|
$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];
|
|
}
|
|
|
|
/*
|
|
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
|
|
*/
|
|
|
|
?>
|