In the Zend Framework 2, using REST Client using the POST method, the post URL has the query string,
As normal in postman when the request is post, the post content i have set
{"authToken":"11111111111111"} and post, status success.
when i get this value using GET method i have get the response, {"authToken":"11111111111111"}
which is correct.
when i run this through, php zend 2 using below method,
protected function genericSendRequest($url, $rawJsonData = NULL, $param = array()){
$response = '';
if(!empty($param)) {
$url .= '?' . http_build_query($param);
}
$client = $this->getHttpClient();
$client->setUri($url);
$client->setMethod('POST');
if($rawJsonData != null) {
$client->setRawBody(json_encode($rawJsonData));
}
$response = $client->send();
if ($response->isSuccess()) {
return $response->getContent();
}
return NULL;
}
Request Input,
$rawJsonData = array("authToken"=>"11111111111111");
$param = array("id"=>"9e770c9f71b4ef1b4ae85c58b0be4280253f9a2e");
Response i got,
id=9e770c9f71b4ef1b4ae85c58b0be4280253f9a2e&%7B%22authToken%22%3A%2211111111111111%22%7D=
This look like a URL query string,
i need the the response {"authToken":"11111111111111"}
ie. I need to get what i have post but i am getting post + query string,
query string is additionally posting to the request, that so its getting in the response,
how should avoid posting this querying string.
what the change needed in my code.?
Any help much appreciated.
Thanks in advance.
You question isn't very clear, but assuming you want to POST JSON data rather than form encoded data, you want:
if ($rawJsonData != null) {
$client->setRawBody(json_encode($rawJsonData));
}
Also, you could rewrite the query string part of your function to just:
if (!empty($param)) {
$uri .= '?' . http_build_query($param);
}
Related
I have a function developed by PHP that at the moment all I want it to do is to return the value of the variable $_POST['token']
I tried:
public function actionGetuserbytoken() {
$data = json_decode(file_get_contents("php://input"), TRUE);
$id = $data['token'];
return $id;
}
Or I also just tried:
public function actionGetuserbytoken() {
return $_POST['token'];
}
I tried doing the POST with Insomnia to check what is going on:
I feel this is a very absurd question but I can't understand why I can't get the value of the POST in either of the two ways.
The php://input stream can only be read once per request. Yii is likely reading the payload before you can, which means that the body is empty when you read the data.
Instead of using php://input, try the following:
$data = json_decode(Yii::app()->request->getRawBody(), true);
I need to re-generate the URL of my page, removing the additional parameters. For example: when I receive:
/bao1/bao2/?removeMe1=anything&keepMe1=anything&removeMe2=&keepMe2=anything
I want to generate the URL with removeMe query var removed, but with everything else intact. Like this:
/bao1/bao2/?keepMe1=anything&keepMe2=anything
I autowired the request:
public function __construct(RequestStack $httpRequest)
{
$this->httpRequest = $httpRequest;
}
Then I'm playing around like this:
public function getCleanUrl()
{
// HttpFoundation\Request
$currentHttpRequest = $this->httpRequest->getCurrentRequest();
// Trying to remove the parameters
$currentHttpRequest->query->remove("removeMe1");
return $currentHttpRequest->getUri()
}
The query->remove("removeMe1") works, but when I invoke getUri() I still get the full input url, as if remove() was never invoked. I think I'm probably missing to call some kind of $currentHttpRequest->regenerate()->getUri() but I cannot find anything.
To get the modified URL after calling mutator methods on a Request object, you need to call overrideGlobals().
If not, Request methods will give you results accordin to the original superglobals ($_GET, $_POST, $_SERVER). By calling Request::overrideGlobals() you tell the object not to.
E.g.:
if ($request->query->has('amp') && Request::METHOD_GET === $request->getMethod()) {
$request->query->remove('amp');
$request->overrideGlobals();
return new RedirectResponse($request->getUri(), Response::HTTP_MOVED_PERMANENTLY));
}
Or maybe, something more adjusted to your use case (untested, but the general idea should hold):
$queryParams = array_keys($request->query->all());
$goodParams = ['foo', 'bar', 'baz'];
$badParams = array_diff($queryParams, $goodParams);
foreach ($badParams as $badParam) {
$request->query->remove($badParam);
}
$request->overrideGlobals();
// get modified URL
echo $request->getUri();
I had to make this work, so I devised a non-Symfony solution:
$currentHttpRequest = $this->httpRequest->getCurrentRequest();
$arrParams = $currentHttpRequest->query->all();
$arrParams = array_intersect_key($arrParams, array_flip([
"keepMe1", "keepMe2"
]));
$currentUrlNoQs = strtok($currentHttpRequest->getUri(), '?');
if( empty($arrParams) ) {
$canonical = $currentUrlNoQs;
} else {
$queryString = http_build_query($arrParams);
$canonical = $currentUrlNoQs . '?' . $queryString;
}
return $canonical;
I'm not too fond of it, but it got the job done.
I have problem with CakePHP request handling…
I wrote an REST API to post some data and files and use multipart/form-data when want to send data.
When sending POST request(Multipart/form-data and send data as json),need to convert $this->request->data from json string to Array:
I wrote below code to convert json data to Array in beforeFilter of my controller:
$parser = function ($data) {
return json_decode($this->request->data,true);
};
$this->RequestHandler->addInputType("file", array($parser));
This is work fine and when I get $this->request->data in controller, JSON data successfully converted to Array,
But If I send request with file, this error happen:
Argument 1 passed to Hash::insert() must be of the type array, string given, called in /home/besepari/public_html/android/lib/Cake/Network/CakeRequest.php on line 401 and defined …
After research on codes,I find the problem but I couldn’t find a way to fix that.I think the error was generated because conversion of $data from json to array(in beforeFilter) happens after of this event so json string passed to Hash::insert() and make the error.need a way to convert json string of $data before of Hash::insert() execution.
Finally I found a way to fix this,but my approach maybe isn't good solution.Because I changed the core of cakephp class.
For fix the bug, replace cakeRequest.php _processFileData() method with this:
protected function _processFileData($path, $data, $field) {
//Fix bug of hash::insert string given(because in json multipart,$this->data is string and made a bug)
//check if string is json,parse it and save it to $this->data
if(!is_array($this->data)){
$parsedData=json_decode($this->data,true);
if (json_last_error() === JSON_ERROR_NONE) {
// JSON is valid
$this->data=$parsedData;
}
}
foreach ($data as $key => $fields) {
$newPath = $key;
if (strlen($path) > 0) {
$newPath = $path . '.' . $key;
}
if (is_array($fields)) {
$this->_processFileData($newPath, $fields, $field);
} else {
$newPath .= '.' . $field;
$this->data = Hash::insert($this->data, $newPath, $fields);
}
}
}
Thanks,
I use cakephp 2
sorry for bad English.
I'm using Zurmo and trying to create a new account using REST API. I followed this documentation precisely: http://zurmo.org/wiki/rest-api-specification-accounts to pass the required parameters as json array.
This is my php code:
public function actionCreateOrUpdate()
{
$params=$_POST;
$modelClassName=$this->getModelName();
foreach ($params as $param)
{
if (!isset($param))
{
$message = Zurmo::t('ZurmoModule', 'Please provide data.');
throw new ApiException($message);
}
$r=$this->GetParam($param);
$res= array('status' => 'SUCCESS', 'data' => array($r));
print_r(json_encode($res,true));
}
}
function GetParam ($param){
$modelClassName=$this->getModelName();
if (isset($param['mobile_id'] ) && !$param['mobile_id']=='' &&!$param['mobile_id']==null)
{ $id=$param['mobile_id'];
$params=array();
foreach ($param as $k => $v) {
if(!($k=='mobile_id')) {
$params[$k] = $v;}
}
if ($params=null){$message = Zurmo::t('ZurmoModule', 'Please provide data.');
throw new ApiException($message);}
$tableName = $modelClassName::getTableName();
$beans = ZurmoRedBean::find($tableName, "mobile_id = '$id'");
if (count($beans) > 0)
{
$result = $this->processUpdate($id, $params);
}else{
$result = $this->processCreate($params,$id);
}
}
return $result;
}
The problem is that the $_POST method is returning an empty array. While debugging I tried to use print_r($_POST) and it also returned an empty array. I also tried to pass parameters as plain text and got the same result. I tried $_GET method and it worked. I think the problem is in the $_POST method, maybe I need to change something in my .php files. Any ideas please?
You should first hit the api with static data, to check if it works fine, then try to integrate php within that static data. You will need to read the documentation for which action accepts which format, and which method is supported(GET OR POST). Then try die(); , before sending if the array formed is as per the documentation.
I had similar issue when creating Account using REST API from java client. The problem was I did not send the proper POST request.
Another symptom also was on server side print_r(file_get_contents("php://input"),true); php code returned the correct request data.
Specifically the root cause was:
The Content-Type HTTP header was not "application/x-www-form-urlencoded"
The value field value in POST request was not properly encoded ( I used java.net.URLEncoder.encode method to overcome this)
After fixing these it worked.
Can I get a HttpRequest automatically created from the environment? In other words, right now it seems like you have to...
$request = new HttpRequest;
$request->setCookies($_COOKIE);
$request->setHeaders(apache_request_headers());
$request->setPostFields($_POST);
$request->setQueryData($_GET);
$request->setRawPostData(file_get_contents('php://input'));
$request->setUrl($_SERVER['REQUEST_URI'']);
We also need to set the method -- a ridiculous chore, since $_SERVER['REQUEST_METHOD'] is a string and HttpRequest::setMethod takes an int in the HTTP_METH_* series of contants. So you have to set up your own mapping.
I want to like HttpRequest, but it seems cumbersome to use at the moment. I hope I'm missing something.
Edit:
The idea is to make testing cleaner. $_COOKIE and friends are superglobals. How do you test that?
function receiveRequest() {
$code = 'that touches superglobals like' . $_COOKIE['example'];
$response = new HttpResponse;
$response->setStatus(200);
return $response;
}
function testServer() {
$oldCookie = $_COOKIE;
$oldPost = $_POST;
// etc...
$_COOKIE = array('example' => 'stuff');
$_POST = array();
// etc...
$response = receiveRequest();
$_COOKIE = $oldCookie;
$_POST = $oldPost;
// etc...
assert($response->getStatus() === 200);
}
You need to control the state of not just what you use -- $_COOKIE in this example -- but every superglobal. There are about a dozen. It would be a lot cleaner to wrap up all that stuff in HttpRequest.
function receiveRequest(HttpRequest $request) {
$code = 'is purely a function of arguments like' . $request->getCookie('example');
$response = new HttpResponse;
$response->setStatus(200);
return $response;
}
function testServer() {
$request = new HttpRequest;
$request->setCookie('example' => 'stuff');
$response = receiveRequest($request);
assert($response->getStatus() === 200);
}
Then my actual server.php would use the hypothetical static method that I'm looking for.
$request = HttpRequest::generateRequestFromEnvironment($_COOKIE, $_POST, ...);
unset($_COOKIE, $_POST, ...);
$response = receiveRequest($request);
$response->send();
This seems to me like an odd use case - you want to create an HttpRequest to...yourself? Using exactly the parameters you were passed? Why?
The normal case is for requesting another resource, from another host, for which the kind of "automatic setup" you desire is pretty useless. If you really need this situation, it seems trivial to wrap this in a function that's easily reused?
From what you've posted, I think you're using HttpRequest as a container for all the information about the request which triggered your script.
This isn't what it is for - it is for making HTTP requests to other services from within your script. For example, you might request data from the Flickr API