From 0709e92b6f2170f6ca5068db8ba9e4f18ab0bfe7 Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 4 Sep 2023 19:45:12 +0200 Subject: [PATCH] handle artifact download correctly --- webinstall/cibuild.php | 115 ++++++++++++++++++++++++--------------- webinstall/functions.php | 96 ++++++++++++++++++++++++++------ webinstall/install.php | 70 ++++++++++++++---------- 3 files changed, 192 insertions(+), 89 deletions(-) diff --git a/webinstall/cibuild.php b/webinstall/cibuild.php index e2fb9c2..77e4979 100644 --- a/webinstall/cibuild.php +++ b/webinstall/cibuild.php @@ -73,50 +73,79 @@ function getArtifacts($job,$slug){ return getJson($url,getTokenHeaders(),true); } -if (isset($_REQUEST['api'])){ - $action=$_REQUEST['api']; - header("Content-Type: application/json"); - $par=array(); - if ($action == 'status') { - addVars( - $par, - ['pipeline', 'workflow', 'job'], - array('workflow' => workflowName, 'job' => jobName) - ); - try { - $pstat = getJobStatus($par['pipeline'], $par['workflow'], $par['job']); - echo(json_encode($pstat)); - } catch (Exception $e) { - $rt=array('status'=>'error','error'=>$e->getMessage()); - echo(json_encode($rt)); - } - exit(0); +function getArtifactsForPipeline($pipeline,$wf=workflowName,$job=jobName){ + $jstat=getJobStatus($pipeline,$wf,$job); + if (! isset($jstat['job_number'])){ + throw new Exception("no job number"); } - if ($action == 'artifacts'){ - addVars( - $par, - ['pipeline', 'workflow', 'job'], - array('workflow' => workflowName, 'job' => jobName) - ); - try{ - $jstat=getJobStatus($par['pipeline'], $par['workflow'], $par['job']); - if (! isset($jstat['project_slug'])){ - throw new Exception("no project_slug in job"); - } - if (! isset($jstat['status'])){ - throw new Exception("no job status"); - } - if ($jstat['status'] != 'success'){ - throw new Exception("invalid job status ".$jstat['status']); - } - $astat=getArtifacts($jstat['job_number'],$jstat['project_slug']); - echo (json_encode($astat)); - }catch (Exception $e){ - echo(json_encode(array('status'=>'error','error'=>$e->getMessage()))); - } - exit(0); + if (! isset($jstat['status'])){ + throw new Exception("no job status"); } - die("invalid api $action"); + if ($jstat['status'] != 'success'){ + throw new Exception("invalid job status ".$jstat['status']); + } + $astat=getArtifacts($jstat['job_number'],$jstat['project_slug']); + return $astat; +} +try { + if (isset($_REQUEST['api'])) { + $action = $_REQUEST['api']; + header("Content-Type: application/json"); + $par = array(); + if ($action == 'status') { + addVars( + $par, + ['pipeline', 'workflow', 'job'], + array('workflow' => workflowName, 'job' => jobName) + ); + try { + $pstat = getJobStatus($par['pipeline'], $par['workflow'], $par['job']); + echo (json_encode($pstat)); + } catch (Exception $e) { + $rt = array('status' => 'error', 'error' => $e->getMessage()); + echo (json_encode($rt)); + } + exit(0); + } + if ($action == 'artifacts') { + addVars( + $par, + ['pipeline', 'workflow', 'job'], + array('workflow' => workflowName, 'job' => jobName) + ); + try { + $astat = getArtifactsForPipeline($par['pipeline'], $par['workflow'], $par['job']); + echo (json_encode($astat)); + } catch (Exception $e) { + echo (json_encode(array('status' => 'error', 'error' => $e->getMessage()))); + } + exit(0); + } + die("invalid api $action"); + } + if (isset($_REQUEST['download'])) { + $pipeline = $_REQUEST['download']; + $par = array('pipeline' => $pipeline); + addVars( + $par, + ['workflow', 'job'], + array('workflow' => workflowName, 'job' => jobName) + ); + $astat = getArtifactsForPipeline($par['pipeline'], $par['workflow'], $par['job']); + if (!isset($astat['items']) || count($astat['items']) < 1) { + die("no artifacts for job"); + } + $dlurl = $astat['items'][0]['url']; + #echo("DL: $dlurl\n"); + proxy($dlurl); + exit(0); + } + die("no action"); +} catch (HTTPErrorException $h) { + header($_SERVER['SERVER_PROTOCOL'] . " " . $h->code . " " . $h->getMessage()); + die($h->getMessage()); +} catch (Exception $e) { + header($_SERVER['SERVER_PROTOCOL'] . ' 500 ' . $e->getMessage()); + die($e->getMessage()); } -die("no action"); ?> \ No newline at end of file diff --git a/webinstall/functions.php b/webinstall/functions.php index 1be14d9..96557a6 100644 --- a/webinstall/functions.php +++ b/webinstall/functions.php @@ -39,6 +39,7 @@ function addVars(&$vars,$names,$defaults=null){ function curl_exec_follow(/*resource*/ $ch, /*int*/ &$maxredirect = null) { $mr = $maxredirect === null ? 5 : intval($maxredirect); + #echo("###handling redirects $mr\n"); if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off') && false) { curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $mr > 0); curl_setopt($ch, CURLOPT_MAXREDIRS, $mr); @@ -48,20 +49,26 @@ function curl_exec_follow(/*resource*/ $ch, /*int*/ &$maxredirect = null) { $newurl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); $rch = curl_copy_handle($ch); curl_setopt($rch, CURLOPT_HEADER, true); - curl_setopt($rch, CURLOPT_NOBODY, true); + #curl_setopt($rch, CURLOPT_NOBODY, true); curl_setopt($rch, CURLOPT_FORBID_REUSE, false); curl_setopt($rch, CURLOPT_RETURNTRANSFER, true); do { + #echo("###trying $newurl\n"); curl_setopt($rch, CURLOPT_URL, $newurl); + curl_setopt($ch, CURLOPT_URL, $newurl); $header = curl_exec($rch); if (curl_errno($rch)) { $code = 0; } else { $code = curl_getinfo($rch, CURLINFO_HTTP_CODE); + #echo("###code=$code\n"); if ($code == 301 || $code == 302) { preg_match('/Location:(.*?)\n/', $header, $matches); $newurl = trim(array_pop($matches)); } else { + if ($code >= 300){ + trigger_error("HTTP error $code"); + } $code = 0; } } @@ -98,7 +105,7 @@ function curl_exec_follow(/*resource*/ $ch, /*int*/ &$maxredirect = null) { return curl_exec($ch); } -function setFw($curl,$aheaders=null){ +function getFwHeaders($aheaders=null){ $headers=getallheaders(); $FWHDR = ['User-Agent']; $outHeaders = array(); @@ -112,41 +119,98 @@ function setFw($curl,$aheaders=null){ array_push($outHeaders,"$hk: $hv"); } } - curl_setopt($curl, CURLOPT_HTTPHEADER, $outHeaders); + return $outHeaders; } -function getJson($url,$headers=null){ +function getJson($url,$headers=null,$doThrow=false){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL,$url); curl_setopt($curl,CURLOPT_RETURNTRANSFER, true); - setFw($curl,$headers); + curl_setopt($curl, CURLOPT_HTTPHEADER, getFwHeaders($headers)); $response = curl_exec($curl); $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); #echo("curl exec for $url:$response:$httpcode\n"); if($e = curl_error($curl)) { curl_close($curl); + if ($doThrow) throw new Exception($e); return array('error'=>$e); } else { if ($httpcode >= 300){ curl_close($curl); + if ($doThrow) throw new Exception("HTTP error $httpcode"); return array('error'=>"HTTP code ".$httpcode); } curl_close($curl); return json_decode($response, true); } } +class HTTPErrorException extends Exception{ + public $code=0; + public function __construct($c,$text){ + parent::__construct($text); + $this->code=$c; + } +}; +function proxy_impl($url, $timeout=30,$headers=null,$num = 5) +{ + $nexturl=$url; + while ($num > 0 && $nexturl != null) { + $num--; + $code=0; + $ch = curl_init($nexturl); + $nexturl=null; + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); + curl_setopt($ch, CURLOPT_TIMEOUT,$timeout); + if ($headers != null){ + curl_setopt($ch,CURLOPT_HTTPHEADER,$headers); + } + curl_setopt( + $ch, + CURLOPT_HEADERFUNCTION, + function ($curl, $header) use(&$nexturl,&$code){ + #echo ("###header:$header\n"); + if ($code == 0){ + $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + } + #echo ("???code=$code\n"); + if ($code == 301 || $code == 302) { + if(preg_match('/Location:(.*?)\n/', $header, $matches)){ + $nexturl = trim(array_pop($matches)); + #echo("???nexturl=$nexturl\n"); + } + } + if ($code != 0 && $code < 300){ + header($header); + } + return strlen($header); + } + ); + curl_setopt( + $ch, + CURLOPT_WRITEFUNCTION, + function ($curl, $body) use(&$code) { + if ($code != 0 && $code < 300){ + #echo ("### body part " . strlen($body)."\n"); + echo $body; + return strlen($body); + } + return false; + } + ); + $rs = curl_exec($ch); + #echo ("###code=$code\n"); + curl_close($ch); + if ($nexturl == null){ + if ($code != 200) throw new HTTPErrorException($code,"HTTP status $code"); + return true; + } + } + throw new HTTPErrorException(500,"too many redirects"); +} + function proxy($url) { - $ch = curl_init($url); - curl_setopt_array( - $ch, - [ - CURLOPT_RETURNTRANSFER => true, - CURLOPT_CONNECTTIMEOUT => 30, - ] - ); - setFw($ch); - $response = curl_exec_follow($ch); - curl_close($ch); + header('Access-Control-Allow-Origin:*'); + return proxy_impl($url,30,getFwHeaders()); } ?> \ No newline at end of file diff --git a/webinstall/install.php b/webinstall/install.php index 2cd046b..ed5281e 100644 --- a/webinstall/install.php +++ b/webinstall/install.php @@ -1,41 +1,51 @@ +} catch (HTTPErrorException $h) { + header($_SERVER['SERVER_PROTOCOL'] . " " . $h->code . " " . $h->getMessage()); + die($h->getMessage()); +} catch (Exception $e) { + header($_SERVER['SERVER_PROTOCOL'] . ' 500 ' . $e->getMessage()); + die($e->getMessage()); +} +die("invalid request"); +?> \ No newline at end of file