PHP Post file_get_contents met body

Codeigniter

Codeigniter ben ik tegen gekomen op mijn werk, waarin we het inzetten om het werk van de consultants te vereenvoudigen. Niet, in de eerste plaats, omdat we lui zijn aangelegd, maar vooral om te voorkomen dat er toch kleine verschillen kruipen in de gezamelijke oplossingen die we bedenken.

De tooling is een framework gebouwd in PHP dat het Model View Controller principe hanteert. Hierdoor werd het vrij gemakkelijk om nieuwe functionaliteiten toe te voegen aan een php applicatie, die op bijna elke http server uitgevoerd kan worden.

curl

binnen onze oplossing werd het duidelijk dat er een middel nodig was om gegevens die ingevoerd werden, richting verschillende CI omgevingen te sturen. Hier gaat het specifiek om GitLab en om Jenkins. De uitleg wat we hier mee proberen te bereiken, is voor nu te vergaand. Daar kunnen we later misschien nog wel een keertje op terugkomen.

We konden gebruik maken van de redelijk bekende tool:

curl

Echter kwamen we erachter dat dit niet op alle servers standaard geinstalleerd was, dus we zochten naar alternatieven. Bleek later de gewone haal content functie van PHP dit ook te kunnen. Daarom zijn we overgestapt op de standaard van php:

file_get_contents

Wat hier echter een probleem opleverde was dat er binnen GitLab er alleen gebruik werd gemaakt van een zogenaamde query paramter string, zoals:

http://www.gitlabserver.nl/api/v4/projects?name=test&owner=doris

Dit werd echter anders met de call richting Jenkins, omdat daar ook echt een bestand of eigenlijk meer de inhoud van een bestand (job.xml) moest worden meegestuurd in de POST sessie.

Wat er hier anders aan was, dat er een 2de element aan het geheel moest worden meegestuurd, naast de parameters. Dit was de code voor het geheel werkte:

function call_rest_api($type_method, $header, $url, $data, $data_binary = NULL)
{
$postdata = http_build_query($data);

$packet['method'] = $type_method;
$packet['header'] = implode("\r\n", $header);
$packet['content'] = $postdata;
if ($data_binary) {
$packet['data-binary'] = "@".$data_binary;
}

$transmit_data = array('http' => $packet);

$context = stream_context_create($transmit_data);
$result = file_get_contents($url, false, $context);

return $result;
}

Dit zorgde ervoor dat de paramters vanuit $data als query werden opgezet met de ‘&’  ertussen, maar dit werd aan de content toegevoegd. Een test om te zien hoe het met binairy data ging, was lastig.

Postman had een mooie methode om nadat ik het geheel werkend had gekregen een middel om source code te laten zien. Echter niet met de file_get_contents en alleen met de curl en HTTP post acties. Maar dat liet wel een duidelijk beeld zien.

Middels Wireshark kwam ik erachter dat mijn data-binary helemaal niet over de lijn ging. De talloze voorbeelden op internet gingen allemaal over het feit dat dit als content of data in de array moest worden meegestuurd, maar dat wilde allemaal niet werken.

Wel kwam ik ergens een voorbeeld tegen, die de content met alleen data liet zien. Alle parameters zaten in de URL. Dus verder geen extra parameters en daarmee leek het anders wel te werken. Vandaar dat ik de parameters die allemaal in de var $postdata kwamen te zitten, heb verplaatst om direct in de URL te zetten en dit is de werkende code geworden:

function call_rest_api($type_method, $header, $url, $data, $data_binary = NULL)
  {
      $postdata = http_build_query($data);
      $url = $url.'?'.$postdata;
      log_message('debug','DEBUG postdata inhoud van de verschillende call_rest_api calls: '.$postdata);
      $packet['method'] = $type_method;
      $packet['header'] = implode("\r\n", $header);

      if ($data_binary) {
          $packet['content'] = $data_binary;
      }

      $transmit_data = array('http' => $packet);

      $context  = stream_context_create($transmit_data);
      $result = file_get_contents($url, false, $context);
      log_message('debug',$result);
      return $result;
  }

Dit is werkende code voor en GitLab en Jenkins!

Geef een reactie

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *