PHP - How to receive a data stream from a Python post?

Asked

Viewed 141 times

-2

I intend to load an authenticated session from a website using cookies sent by an application made in Python not encoded by me.

As shown in the image below, the data is sent via post in a byte stream. The question is, how to receive and treat this data correctly for use in the option CURLOPT_COOKIE of curl in a PHP script ?

Imagem do código Python

This way works properly if using the file cookies.txt locally.

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => false,
    CURLOPT_COOKIE => 'cookies.txt',
    CURLOPT_COOKIEFILE => 'cookies.txt'
]);

$response = curl_exec($ch);
echo $response;

curl_close($ch);

?>

But this way receiving cookies through a post python does not load session correctly.

$cookiedata = var_dump($_POST);

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => false,
    CURLOPT_COOKIE => $cookiedata,
    CURLOPT_COOKIEFILE => 'cookies.txt'
]);

$response = curl_exec($ch);
echo $response;

curl_close($ch);

?>

I think that’s all.

1 answer

1


First, reading the documentation helps a lot, rather than programming by kicking how things work.

According to, is so much error in your code, You can see right away that this is wrong:

CURLOPT_COOKIE => 'cookies.txt',

Because CURLOPT_COOKIE as described in the documentation https://www.php.net/manual/en/function.curl-setopt.php serves to manually set cookies with a string, it would be the same to set the header Cookie: foo=bar, so if you’re using the.txt cookie and you don’t want to set a fixed value then it doesn’t even make sense to use it.

Another thing, you used CURLOPT_RETURNTRANSFER => false, and then $response = curl_exec($ch); doesn’t make any sense, in the documentation is written:

TRUE to Return the transfer as a string of the Return value of curl_exec() Instead of outputting it out directly.

Translating:

TRUE to return the transfer as a "string" of the return value "curl_exec()" instead of sending directly to "OUTPUT".

Now that was the most wrong and senseless:

 $cookiedata = var_dump($_POST);

The function var_dump ALWAYS RETURNS NULL and only returns something when using the second parameter as true thus var_dump($array, true), but just for the record, even if it did return values MAKES NO SENSE use var_dump to pass POST values to cookies.

If you want to send the post as cookies then you have to "pin" to the post itself CURLOPT_COOKIE, something else the CURLOPT_COOKIEFILE not to keep your "cookies saved", would be almost equivalent to CURLOPT_COOKIE, and what "differs" him from CURLOPT_COOKIEJAR is that the cookie receives all cookies and maintains them for other future requests, i.e.:

  • CURLOPT_COOKIEFILE to set "fixed cookies"
  • CURLOPT_COOKIEJAR to maintain cookies set in the next requests, is saved when used the curl_close, because cookies may come from the requested page

People usually mix both files, which doesn’t make any sense.

Now to solve your problem, let’s simply explain in parts, first take the POST values, you can iterate and generate a string like this:

//Um array para receber os POST
$cookies = array();

//Itera o POST
foreach($_POST as $name => $value) {

     //Adiciona item por item no array no formato "foo=bar"
     if (is_string($value)) {
         $cookies[] = urlencode($name) . '=' . urlencode($value);
     }
}

//Junta todos para o formato aceito pelo header Cookie: foo-bar; abc=123
$cookiedata = implode(';', $cookies);

However note that it has a simpler function to do this, the http_build_query, could even use this in one line:

$cookiedata = http_build_query($_POST);

But if the payload received is something like:

user[name]=Bob+Smith&user[age]=47&user[sex]=M&user[dob]=5%2F12%2F1956&pastimes[0]=golf&pastimes[1]=opera&pastimes[2]=poker&pastimes[3]=rap&children[bobby][age]=12&children[bobby][sex]=M&children[sally][age]=8&children[sally][sex]=F&flags_0=CEO

Then it will disturb a little the structure of cookies, not much, but enough to generate cookies that certainly would not be what you want, so I used the is_string in the foreach, of course it does not guarantee much, but it is the basic.

Second, you must send the variable $cookies on CURLOPT_COOKIE only, something like:

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_COOKIE => $cookiedata
]);

$resposta = curl_exec($ch);

Third, note that I used CURLOPT_RETURNTRANSFER => true, because this will return to variable, but remember that this will be used if it is what you want, if you do not want this and just want to display direct so do not even need to set, it should be just this:

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_COOKIE => $cookiedata
]);

curl_exec($ch);
curl_close($ch);

Now an additional note, note that any and all HTTP responses may contain a redirect or more, so ideally set:

  • CURLOPT_FOLLOWLOCATION to redirect automatically (internally)
  • CURLOPT_MAXREDIRS limits redirects, because the page you are accessing may have some "bug" that makes infinite redirects, a value maybe ideal here is to limit to 10, but it is only suggestion.

Should stay:

curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_COOKIE => $cookiedata,
    CURLOPT_FOLLOWLOCATION => true, //Ativa o redirecionamento
    CURLOPT_MAXREDIRS => 10  //limita os redirecionamentos para 10
]);

It would also be interesting for most cases to handle the HTTP responses, for your case I don’t know, because it is you who controls the python page, but assuming a page emits a different code than range 2xx then you should treat this with curl_getinfo+CURLINFO_HTTP_CODE, example:

$resposta_http = curl_getinfo($request, CURLINFO_HTTP_CODE);

//Qualquer código fora do range 200 e 299 provavelmente é pagina de erro
if ($resposta_http < 200 && $resposta_http > 299) {
    $resposta = false;
}

If you want to get the result then use it this way (probably this is what you want, but I have no way of knowing):

//Um array para receber os POST
$cookies = array();

//Itera o POST
foreach($_POST as $name => $value) {

     //Adiciona item por item no array no formato "foo=bar"
     if (is_string($value)) {
         $cookies[] = $name . '=' . $value;
     }
}

//Junta todos para o formato aceito pelo header Cookie: foo-bar; abc=123
$cookiedata = implode(';', $cookies);

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_COOKIE => $cookiedata,
    CURLOPT_RETURNTRANSFER => true,  //Pega resposta em uma var
    CURLOPT_FOLLOWLOCATION => true, //Ativa o redirecionamento
    CURLOPT_MAXREDIRS => 10  //limita os redirecionamentos para 10
]);

$resposta = curl_exec($ch);

//Verifica se conectou e baixou algo, mesmo que tenha um código HTTP de erro
if ($resposta !== false) {

    //Pega O CÓDIGO da resposta HTTP
    $resposta_http = curl_getinfo($request, CURLINFO_HTTP_CODE);

    //Qualquer código fora do range 200 e 299 provavelmente é pagina de erro
    if ($resposta_http < 200 && $resposta_http > 299) {
        //Seta false para evitar continuar o processo no proximo IF
        $resposta = false;
    }
} else {
    $resposta_http = 0;
}

curl_close($ch);

if ($resposta) {
    echo $resposta; //coloquei um ECHO mas aqui você pode fazer o que quiser com a resposta
} elseif ($resposta_http > 0) {
    echo 'Ocorreu o erro HTTP: ' . $resposta_http;
} else {
    echo 'Não foi possivel se conectar com o servidor';
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.