Guzzle encodes body to Json, but I want form data - php

I'm tyring to post something to Googles oAuth server to do some authentication. Google really wants this information in form data (Content-Type: application/x-www-form-urlencoded) but my guzzle client seems to insist (as far as I can tell) on making the body JSON. I'm using Guzzle 4.*
I've changed my URL to a PostCatcher.io url, so I can see what comes out (because for the life of my I can't figure out how to see the actual raw HTTP request that guzzle spits out), and it looks like theres JSON coming out.
My code (I'm using a test url by now):
$client = new GuzzleClient();
$url = "https://www.googleapis.com/" . "oauth2/v3/token";
$test_url = 'http://postcatcher.in/catchers/55602457b92ce203000032ae';
$request = $client->createRequest('POST', $test_url);
$request->setHeader('Content-Type', 'application/x-www-form-urlencoded'); //should be redundant
$body = $request->getBody();
$body->setField('code', $code);
$body->setField('client_id', $this->client_id);
$body->setField('client_secret', $this->client_secret);
$body->setField('redirect_url', $this->redicrect_url);
$body->setField('grant_type', $this->grant_type);
try {
$response = $client->send($request);
$result = $response->getBody();
return $result;
} catch (\Exception $exc) {
return $exc->getCode() . ' ' . $exc->getMessage();
}
The documentation says this should be enough. What am I missing ?

Using Guzzle 5.2 I've done the same thing with:
$request = $this->createRequest(
$method,
$uri,
['body' => $php_array_of_values ]
);
$response = $this->send($request);

I found the problem. I did upgrade to Guzzle 5.* tho I suspect that wasn't actually the solution.
I just neede to look at the response content. So in the exception clause of the call I added:
if ($exc->hasResponse()) {
return $exc->getResponse()->json();
}
Which gave me a clear error message from Google. The error message was "Missing parameter: redirect_uri". And that's because I had written url instead of uri.
Fixed that, and now it's all good.

Related

How to use Rest API and PHP

Very beginner question but simply do not know where to begin. I am trying to obtain a response with this API using PHP but cannot get anything to work.
I know the problem has something to do with HTTP Components but I'm a total beginner and very stuck.
Any help would be great or perhaps if there's another (cleaner and easier) way to do this would be great as well.
I am trying to get the response in json format
<?php
// This sample uses the Apache HTTP client from HTTP Components (http://hc.apache.org/httpcomponents-client-ga/)
require_once 'HTTP/Request2.php';
$request = new Http_Request2('https://services.last10k.com/v1/company/{ticker}/ratios');
$url = $request->getUrl();
$headers = array(
// Request headers
'Ocp-Apim-Subscription-Key' => '{subscription key}',
);
$request->setHeader($headers);
$parameters = array(
// Request parameters
);
$url->setQueryVariables($parameters);
$request->setMethod(HTTP_Request2::METHOD_GET);
// Request body
$request->setBody("{body}");
try
{
$response = $request->send();
echo $response->getBody();
}
catch (HttpException $ex)
{
echo $ex;
}
?>

How to Log the Zend_Http_Client request

I'm trying to log my request before i do it, to know really what i'm sending example:
I have this code:
$client = new Zend_Http_Client();
$client->setUri($uri);
$client->setConfig(array('timeout' => 30));
$client->setHeaders('Content-Type: application/xml');
$client->setMethod('POST');
$client->setParameterPost('PartnerID', 'xxx');
$client->setParameterPost('Password', 'XXXXXXXXX');
before i do the request i wanna know what i'm sending, something like that:
$request = json_encode($client);
Log::notice("Request: " . $request);
or:
Log::notice("Request: " . $client);
But doesn't work...
I can log the response like that:
$response = $client->request();
Log::notice("Response: " . $response);
Like that i can see the response json, but i wanna know the request that i'm doing.
Thank u all.
You get the last request with function Zend_Http_Client->getLastRequest(). Be aware that the function returns a string and you may have to add some code to fit it in a meaningful JSON output. Add the following to your code:
$request = $client->getLastRequest()
// make your changes to support JSON
Log::notice("Request: " . $request)
The function is also mentioned in the on-line documentation at Introduction - Zend_Http - Zend Framework - Accessing Last Request and Response.

How to add form data on Post requests for Buzz HTTP Client on Laravel?

I'm using Buzz HTTP Client for Laravel.
I have a problem adding form data to my POST requests, since it wasn't specified in it's wiki/documentation.
Listed below are the two ways of sending requests.
Example 1:
$response = Buzz::post('http://api.website.com/login');
//how do I add a "username", and "password" field in my POST request?
echo $response;
echo $response->getContent;
Example 2:
$request = new Buzz\Message\Request('POST', '/', 'http://google.com');
$response = new Buzz\Message\Response();
//how do I add a "username", and "password" field in my POST request?
$client = new Buzz\Client\FileGetContents();
$client->send($request, $response);
echo $request;
echo $response;
The answer here is going to really depend on what the API expects. Lets assume, the API expects the password and username sent as JSON in the content of the request. The example http request would look something like:
POST /login HTTP/1.1
Content-Type: application/json
{
"username": "bugsBunny",
"password": "wh4tsUpD0c"
}
To do this with Buzz, this should work:
$jsonPayload = json_encode([
‘username’ => ‘bugsBunny’,
‘password’ => ‘wh4tsUpD0c
]);
$headers = ['Content-Type', 'application/json'];
$response = Buzz::post('http://api.website.com/login', $headers, $jsonPayload);
If you're attempting to submit a form on a given website, you shouldn't use the above method. Instead use Buzz's built in form method which will attach the correct headers.
use Buzz\Message\Form;
$request = new Form(Form::METHOD_POST, ‘login’, ‘api.website.com’);
$request->setFields([
‘username’ => ‘bugsBunny’,
‘password’ => ‘wh4tsUpD0c’
]);
$response = new Buzz\Message\Response();
$client = new Buzz\Client\Curl();
$client->send($request, $response);
On a side note, I'd suggest not using this library. The library is, as you stated, Laravel integration for Buzz. The issue here is, the author should have made buzz a dependency listed in composer, rather than include the Buzz source directly. This prevents updates to Buzz from making their way into this project. You can see on the actual Buzz repo, the last commit was 29 days ago. Also if another package is using Buzz and including it correctly by composer, composer would install both packages. But when an instance of Buzz was created, you couldn't be certain which version was being loaded. You should just use Buzz, which can be found on packagist.
// assuming $headers and $jsonPayload are the same as in previous example.
$browser = new Buzz\Browser();
$response = $browser->post('http://api.website.com/login', $headers, $jsonPayload);
It was foolish of me to not read the code first before asking.
The form data is actually pased on the third parameter for the function. Though it accepts strings only so don't forget to json encode your data.
Buzz Class
public function post($url, $headers = array(), $content = '')
{
....
....
}
Buzz::post($url, array(), json_encode(array('Username'=>'usernamexx','Password'=>'p#$$w0rD')) );

Send raw json HTTP request for an API call in Yii 1.x.x

I asked a similar question earlier, in a nutshell I have an API application that takes json requests and outputs an json response.
For instance here is one of the requests that I need to test out, how can I use this json object with my testing to emulate a 'real request'
{
"request" : {
"model" : {
"code" : "PR92DK1Z"
}
}
The response is straightforward (this bit has been done).
From other users on here this is the optimised method using Yii to do this, I am just unsure how to emulate the json request - e.g essentially send a JSON HTTP request, can anyone assist on how to do this?
public function actionMyRequest() {
// somehow add my json request...
$requestBody = Yii::app()->request->getRawBody();
$parsedRequest = CJSON::decode($requestBody);
$code = $parsedRequest["request"]["model"]["code"];
}
I don't understand if you want your app to send an http request and get the result or at the opposite receive a http request
I answered for the first assumption, I'll change my answer if you want the other
For me the best way to send an HTTP request is to use Guzzle http client.
This is not a yii extension, but you can use third party libraries with yii.
Here's an example from Guzzle page:
$client = new GuzzleHttp\Client();
$res = $client->get('https://api.github.com/user', [
'auth' => ['user', 'pass']
]);
echo $res->getStatusCode(); // 200
echo $res->getHeader('content-type'); // 'application/json; charset=utf8'
echo $res->getBody();
So in your case you could do something like:
public function actionMyRequest() {
$client = new GuzzleHttp\Client();
$res = $client->get('https://api.your-url.com/');
$requestBody = $res->getBody();
$parsedRequest = CJSON::decode($requestBody);
$code = $parsedRequest["request"]["model"]["code"];
}

NuSOAP: how to change content-type of request?

When consuming a .NET WCF webservice I get the following response (error):
Unsupported HTTP response status 415
Cannot process the message because the content type 'text/xml; charset=UTF-8'
was not the expected type 'application/soap+xml; charset=utf-8'.
How do I change the content type? I can't find it in the NuSOAP forums/docs, or I might be overlooking something....
i know this is an old post, but i ran in to this page looking for an answer.
application/soap+xml is the content-type passed when using SOAP 1.2,
text/xml is used with SOAP 1.1,
something like this should do the trick,
$client = new SoapClient("some.wsdl", array('soap_version' => SOAP_1_1));
You can specify the encoding of NuSOAP streams with the webservices like that :
$client = new nusoap_client($params);
$client->soap_defencoding = 'UTF-8';
It looks like there's a slight omission in the NuSOAP library... it assumes that the content headers MUST be "text/xml", so if your client is attempting to connect to a service that outputs application/soap+xml headers, you'll end up with errors like:
Response not of type text/xml: application/soap+xml; charset=utf-8
To test this, you may benefit from the following little function pattern, which I used to login to a SOAP service. Remember, print out the client object! You may not actually get a result to look at!
require_once('path/to/downloaded/libraries/nusoap.php');
var $endpoint = 'https://somedomain.com/path/to/soap/server/Login';
var $client; // the soapclient object
function SOAP_Login()
{
$this->client = new soapclient($this->endpoint);
$err = $this->client->getError();
if ($err)
{
// Display the error
echo '<p><b>SOAP Constructor error: ' . $err . '</b></p>';
exit;
// At this point, you know the call that follows will fail
}
$params = array(
'some' => 'thing.. depends on what the WSDL expects'
);
$result = $this->client->call('someFunction', $params);
print_r($result); // Without the fix, this prints nothing (i.e. false) !!!
print_r($this->client); // Instead, look at the state of the client object, specifically error_str and debug_str
}
When I printed my $result, I got nothing, but when I printed out the $client object, I could see that there were errors.
The little hack I implemented was in the nusoap.php file, around line 7500. Look for this if-statement:
if (!strstr($headers['content-type'], 'text/xml')) {
$this->setError('Response not of type text/xml: ' . $headers['content-type']);
return false;
}
And change it to this:
if (!strstr($headers['content-type'], 'text/xml') && !strstr($headers['content-type'], 'application/soap+xml') ) {
$this->setError('Response not of type text/xml: ' . $headers['content-type']);
return false;
}
All this does is it lets NuSOAP handle responses that issue an "application/soap+xml" header (which is a valid xml header).
I was stuck on this as well.
The secret is in the web.config
Change wsHttpBinding to basicHttpBinding
Like so:
<endpoint address="" binding="basicHttpBinding" contract="YourProject.View.Whatever.IYourService">
Hope that helps!
/Erik
This worked for me:
$client = new nusoap_client($params);
$client->soap_defencoding = 'UTF-8';
The answer that is ticked as correct is not for NUSOAP therefore not the appropriate answer.

Categories