简体   繁体   中英

Send array of floats as HTTP POST request in php

I am writing a script to be executed by a client which will generate an array of floats (which I understand in PHP are supposed to be the same as doubles) and perform a post request to a page which will take the data and compute the mean, returning that data in the response. My plan is to attach send the array in the message body in json format. I found a tutorial online for doing POST requests in PHP from which I have taken the function do_post_request() and I can't get around the following exception:

PHP Fatal error:  Uncaught exception 'Exception' with message 'Problem with http://localhost/average.php' in /home/yak/restclient.php:20
Stack trace:
#0 /home/yak/restclient.php(5): do_post_request('http://localhos...', '[1.5,1.5,1.5,1....', 'Content-Type=ap...')
#1 {main}
    thrown in /home/yak/restclient.php on line 20

The client code:

<?php
$array = array_fill(0,5,1.5);
$data = json_encode($array);
echo $data;
$response = do_post_request("http://localhost/average.php",$data,"Content-Type=application/json");
echo $response;

function do_post_request($url, $data, $optional_headers = null)
{
  $params = array('http' => array(
              'method' => 'POST',
              'content' => $data
            ));
  if ($optional_headers !== null) {
    $params['http']['header'] = $optional_headers;
  }
  $ctx = stream_context_create($params);
  $fp = @fopen($url, 'r', false, $ctx);
  if (!$fp) {
    throw new Exception("Problem with $url");
  }
  $response = @stream_get_contents($fp);
  if ($response === false) {
    throw new Exception("Problem reading data from $url);
  }
  return $response;
}
?>

Would anybody be able to shed some light on this error, or better yet, suggest a better way of doing what I'm trying to do here? I have also tried using the http_post_data() function, but even after trying some fixes found on SO, I have been unable to get it to work (PHP sees it as an undefined function).

This is the server code:

<?php
header("Content-Type:application/json");
if(!empty($_POST['data'])) {
#calculate mean of each array and send results
    $data = $_POST['data'];
    $array = json_decode($data);
    $mean = array_sum($array)/count($array);
    respond(200,"OK",$mean);
} else {
#invalid request
    respond(400,"Invalid Request",NULL);
}
function respond($status,$message,$data) {
    header("HTTP/1.1 $status $message");
    $response['status']=$status;
    $response['message']=$message;
    $response['data']=$data;
    $json_response=json_encode($response);
    echo $json_response;
}
?>

This will eventually be adapted to deal with several arrays sent in one message, but to get started I thought this would be quite simple - I was wrong.

UPDATE: Using Arpita's answer the request is now going through but the response indicates an invalid request, as if it is not actually doing a POST.

Try using Curl instead

$feed = http://some.url/goes/here
$ch = curl_init($feed);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
echo $result = curl_exec($ch);

Notice the curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json')); replace 'Accept: application/json' with what ever your output format would be.

Pretty much the same as the other answer, I would go with cURL and call this function like you're doing it already, but using : instead of = in the optional headers as an array :

Client side

<?php
// $url is a string with the URL to send the data to
// $data is an associative array containing each value you want to send through POST, for example: array( 'data', json_encode($array, TRUE) );
// $optional_headers is a normal array containing strings (key:value, using ":" instead of "="), for example: array( 'Content-Type: application/json' );

function do_post_request($url, $data, $optional_headers)
{
    $ch = curl_init( $url );

    curl_setopt( $ch, CURLOPT_POST, TRUE ); // People usually use count($data) or even just 1 instead of TRUE here, but according to the documentation, it should be TRUE (any number greater than 0 will evaluate to TRUE anyway, so it's your personal call to use one or another)
    curl_setopt( $ch, CURLOPT_POSTFIELDS, serialize($data) );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, TRUE );
    curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, TRUE ); // Not harmful, will follow Location: header redirects if the server sends them
    curl_setopt( $ch, CURLOPT_HTTPHEADER, $optional_headers );

    return curl_exec( $ch );
}


$array = array_fill(0,5,1.5);
$data = json_encode($array);
echo $data;
$response = do_post_request("http://localhost/average.php", $data, array('Content-Type: application/x-www-form-urlencoded', 'Accept: application/json')); // Note the difference: Content-Type says what you are SENDING, Accept is what you will ACCEPT as an answer. You're sending an encoded JSON inside a usual FORM format, so your Content-Type will be an HTML FORM format instead of a JSON one (in other words: you're sending a STRING that represents the JSON inside a FORM ARRAY)
echo $response;

?>

To clarify the last point (the optional headers with Content-Type), when you say Content-Type: application/json you should be sending a JSON string, I mean, for example:

[1, 2, 5, 3, 4] (POST URL-encodes to: %5B1%2C+2%2C+5%2C+3%2C+4%5D )

But you're actually sending this (which is Content-Type: application/x-www-form-urlencoded ):

data=[1, 2, 5, 3, 4] (POST URL-encodes to: data=%5B1%2C+2%2C+5%2C+3%2C+4%5D )

application/x-www-form-urlencoded accepts key-value pairs just like the ones in a GET URL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM