How to Switch from Post to Get in PHP Curl

How to switch from POST to GET in PHP CURL

Solved: The problem lies here:

I set POST via both _CUSTOMREQUEST and _POST and the _CUSTOMREQUEST persisted as POST while _POST switched to _HTTPGET. The Server assumed the header from _CUSTOMREQUEST to be the right one and came back with a 411.

curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'POST');

PHP Curl GET & POST

This works

$fields = array (
'searchPaginationResultsPerPage' => 500,
'searchPaginationPage' => 1
);

$headers = array (
"Connection: keep-alive",
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Encoding: gzip,deflate,sdch",
"Accept-Language: en-US,en;q=0.8",
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3"
);

$fields_string = http_build_query ( $fields );
$cookie = 'cf6c650fc5361e46b4e6b7d5918692cd=49d369a493e3088837720400c8dba3fa; __utma=148531883.862638000.1335434431.1335434431.1335434431.1; __utmc=148531883; __utmz=148531883.1335434431.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); mcs=698afe33a415257006ed24d33c7d467d; style=default';
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, 'http://www.microgenerationcertification.org/mcs-consumer/installer-search.php?searchPaginationPage=1&searchPaginationResultsPerPage=500' );
curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT, 80 );
curl_setopt ( $ch, CURLOPT_COOKIE, $cookie );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $headers );

$str = curl_exec ( $ch );
curl_close ( $ch );

echo $str;

You needed cookie information and make sure curl is using GET not POST

See Demo : http://codepad.viper-7.com/gTThxX (I hope the cokkies is not expired before you view it )

PHP, cURL, and HTTP POST example?

<?php
//
// A very simple PHP example that sends a HTTP POST to a remote site
//

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
"postvar1=value1&postvar2=value2&postvar3=value3");

// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS,
// http_build_query(array('postvar1' => 'value1')));

// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$server_output = curl_exec($ch);

curl_close ($ch);

// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>

php with Curl: follow redirect with POST

curl is following what RFC 7231 suggests, which also is what browsers typically do for 301 responses:

  Note: For historical reasons, a user agent MAY change the request
method from POST to GET for the subsequent request. If this
behavior is undesired, the 307 (Temporary Redirect) status code
can be used instead.

If you think that's undesirable, you can change it with the CURLOPT_POSTREDIR option, which only seems very sparsely documented in PHP but the libcurl docs explains it. By setting the correct bitmask there, you then make curl not change method when it follows the redirect.

If you control the server end for this, an easier fix would be to make sure a 307 response code is returned instead of a 301.

PHP/CURL - Making a POST request to another page and following the URL

How about this? It assumes name, amount and email will be posted to process.php

Added trouble shooting code.

process.php

 <?php

//[put database queries here]

// $message = ??????????????????

$message = 'Message';

$post = array(
'name'=>$_POST['name'],
'amount'=>$_POST['amount'],
'email'=>$_POST['email'],
'message'=>$message);

$ch = curl_init('http://www.example.com/display.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING,"");

header('Content-Type: text/html');
$data = curl_exec($ch);
echo $data;
?>

This was tested and works too

does the redirect to the actual site.

<?php
$name = $_POST["name"];
$amount = $_POST["amount"];
$email = $_POST["email"];
$message = $_POST["message"];

echo <<< EOT
<html><head><style></style></head><body>
<form id="form" action="http://www.example.com/display.php" method="post">
<input type="hidden" name="name" value="$name"/>
<input type="hidden" name="amount" value="$amount"/>
<input type="hidden" name="email" value="$email"/>
<input type="hidden" name="message" value="$message"/>
</form>

<script>document.getElementById("form").submit();</script>
</body></html>
EOT;

?>

Where to find a changing PHP POST data

2 obvious problems, you don't urlencode your data, so if the data contains & or = or spaces or ÆØÅ or a bunch of other characters, you'll send the wrong data.

second problem is that your curl code use application/x-www-urlencoded encoding, but your browser use multipart/form-data-encoding in the POST request body.

now with curl_, in order to use use multipart/form-data-encoding, just give CURLOPT_POSTFIELDS an array, and curl will multipart/form-data-encode it for you :)

$post_parameters = array (
"auth_key" => $authKey,
"referer" => $referer,
"ips_username" => $username,
"ips_password" => $password
);

edit: fixed some code-breaking typos, had = in the array key name when converting it from urlencoded to php array

as for the confusion about the boundary string, its you, yourself, that decide what the boundary string is. usually, its just a bunch of random characters. its part of the multipart/form-data encoding... but you don't have to worry about that, as curl will make a boundary string for you automatically, and you don't need to know how it works or what it is, curl will take care of it for you.

Curl : * Violate RFC 2616/10.3.2 and switch from POST to GET

CURLOPT_POSTREDIR can be set to configure this behaviour (request method for 301 location header based automatic redirects in curl):

curl_setopt( , CURLOPT_POSTREDIR, 3);

here 3 tells curl module to redirect both 301 as well as 302 requests.

0,1,2,3 are the valid options for the last argument.

0 -> do not set any behavior

1 -> follow redirect with the same type of request only for 301 redirects.

2 -> follow redirect with the same type of request only for 302 redirects.

3 -> follow redirect with the same type of request both for 301 and 302 redirects.

See as well: Request #49571 CURLOPT_POSTREDIR not implemented which has some useful comments, like setting a custom request method:

curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST"); 

Convert PHP curl POST request with array of parameters to Python code

PHPs http_build_query and it's corresponding $_GET and $_POST parsing are completely arbitrary in how they work. Thus you must implement this functionality yourself.

Let's compare the outputs of PHPs http_build_query to pythons urlencode (which requests uses internally to build the parameters)

PHP

$req = array(
'check' => 'command',
'parameters' => array(
0 => array('parameter' => '1', 'description' => '2'),
1 => array('parameter' => '3', 'description' => '4')
)
);
$query = http_build_query($req);
$query_parsed = urldecode($query);
echo $query;
echo $query_parsed;

Result:

check=command¶meters%5B0%5D%5Bparameter%5D=1¶meters%5B0%5D%5Bdescription%5D=2¶meters%5B1%5D%5Bparameter%5D=3¶meters%5B1%5D%5Bdescription%5D=4
check=command¶meters[0][parameter]=1¶meters[0][description]=2¶meters[1][parameter]=3¶meters[1][description]=4

Python

from urllib.parse import urlencode, unquote
req = {'check': 'command', 'parameters': ({'parameter': '1', 'description': '2'}, {'parameter': '3', 'description': '4'})}
query = urlencode(req)
query_parsed = unquote(query)
print(query)
print(query_parsed)

Result:

check=command¶meters=%28%7B%27parameter%27%3A+%271%27%2C+%27description%27%3A+%272%27%7D%2C+%7B%27parameter%27%3A+%273%27%2C+%27description%27%3A+%274%27%7D%29
check=command¶meters=({'parameter':+'1',+'description':+'2'},+{'parameter':+'3',+'description':+'4'})

This looks quite a bit different but apparently conforms to the standard and thus httpbin interprets this correctly.

To make python behave the same as PHP, I've adapted this answer to create the following:

from collections.abc import MutableMapping
from urllib.parse import urlencode, unquote

def flatten(dictionary, parent_key=False, separator='.', separator_suffix=''):
"""
Turn a nested dictionary into a flattened dictionary
:param dictionary: The dictionary to flatten
:param parent_key: The string to prepend to dictionary's keys
:param separator: The string used to separate flattened keys
:return: A flattened dictionary
"""

items = []
for key, value in dictionary.items():
new_key = str(parent_key) + separator + key + separator_suffix if parent_key else key
if isinstance(value, MutableMapping):
items.extend(flatten(value, new_key, separator, separator_suffix).items())
elif isinstance(value, list) or isinstance(value, tuple):
for k, v in enumerate(value):
items.extend(flatten({str(k): v}, new_key, separator, separator_suffix).items())
else:
items.append((new_key, value))
return dict(items)

req = {'check': 'command', 'parameters': ({'parameter': '1', 'description': '2'}, {'parameter': '3', 'description': '4'})}
req = flatten(req, False, '[', ']')
query = urlencode(req)
query_parsed = unquote(query)
print(query)
print(query_parsed)

Which outputs

check=command¶meters%5B0%5D%5Bparameter%5D=1¶meters%5B0%5D%5Bdescription%5D=2¶meters%5B1%5D%5Bparameter%5D=3¶meters%5B1%5D%5Bdescription%5D=4
check=command¶meters[0][parameter]=1¶meters[0][description]=2¶meters[1][parameter]=3¶meters[1][description]=4

which seems to be what you want.

Now you should be able to pass the result of flatten as data to get the desired behaviour.



Related Topics



Leave a reply



Submit