Is possible to do set form data and follow redirect by action in any http client in PHP?
For example I have Guzzle:
$response = $client->request('POST', 'https://example.com/login', [
'form_params' => [
'login' => 'admin',
'pass' => 'admin'
]
]);
Instead get data to variable $response, I would like to be redirected to https://example.com/login, same as if I would send a form manually.
I can do one additional step where I generate form and send it by javascript, but I would like to skip this step.
Related
$client = new Client([
'base_uri' => 'http://localhost',
]);
$response = $client->request('POST', '/API/customerOrder/createOrder.php', [
'json' =>[
'SKU_QUANTITY' => [9,7,8],// we send the array of 3 elements to specific ID array.
'CUSTOMER_ID'=>[12,23,34] // This is the array which contain ID.
]
]);
Welcome to Stackoverflow!
If you are using Laravel and consuming the internal APIs using Guzzle, your request seems correct, however the data that you are posting to the endpoint could be incorrect. Here is an example of how it should be:
use Illuminate\Support\Facades\Http;
$response = Http::post('http://example.com/users', [
'name' => 'Steve',
'role' => 'Network Administrator',
]);
In your case, the request would be:
$data = [
'SKU_QUANTITY' => [9,7,8],
'CUSTOMER_ID'=>[12,23,34],
];
$response = Http::post('/API/customerOrder/createOrder.php', $data);
And in the API route that handles your request, you can get the data as follow:
$customerIdsArray = $request->get('CUSTOMER_ID');
//to get first element of the customer array you would use:
$Id1 = $customerIdsArray[0];
You could iterate the array and process the IDs as per your requirement.
I am trying to send multiple posts to Twilio using Guzzle. My apologizes, I'm very new to guzzle. I have seen some examples where I can set an array of URIs and run the posts in parallel. But I haven't been able to figure out how to use the same URI with different parameters for each request.
The ONLY difference between each call would the the "TO" field. The body, messageSID, and auth would stay the same for each parallel call. I wanted to get this test working then eventually just be able to build the array of anywhere from 1 to 100 TO phone numbers.
Here is my code to send one request:
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client(["base_uri" => "https://api.twilio.com/2010-04-01/Accounts/"]);
$options = array(
'form_params' => [
"Body" => "hello world",
"To" => "+12015551234",
"MessagingServiceSid" => "MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
],
'auth' => [
"accountsidxxxxxxxxxxx",
"tokenxxxxxxxxxxxxxxx"
]
);
$response = $client->post("ACxxxxxxxxxxxxxxxxxxxxx/Messages.json", $options);
echo $response->getBody();
I've two working project communicating between each other via an API built in a Laravel. So far there is only simple POST requests made with GuzzleHttp 6.
And I am currently trying to have a new POST request made from 1 to 2, which would send a couple of simple fields along with one file.
Project 1 has a form, on the form submit I handle the data and want to send them to project 2 via a POST request to this new API endpoint.
I've tried different guzzle options 'multipart', 'form_data' etc and realised they may not be combined together. Now I understood that this options are exclusive and using only "multipart" seems the way to go.
But when I send my request to Laravel no data nor file are there.
Here is the code for my request
$options = [
'multipart' =>
[
[
'name' => 'data',
'contents' => '{"field_1":"Test","field_2":"Test","field_3":"Test"}',
'headers' =>
[
'Content-Type' => 'application/json',
],
],
[
'name' => 'file',
'filename' => 'test.pdf',
'Mime-Type' => 'application/pdf',
'contents' => file_get_contents($_FILEs['text_file']['temp_name']),
]
]
];
$this->client->request('POST', "api/test_post", $options)
I also gve this a try:
$options = [
'multipart' =>
[
[
'name' => 'field_1',
'contents' => 'Test',
],
[
'name' => 'field_2',
'contents' => 'Test',
],
[
'name' => 'file',
'filename' => 'test.pdf',
'Mime-Type' => 'application/pdf',
'contents' => fopen($_FILEs['text_file']['temp_name'],'r'),
]
]
];
$this->client->request('POST', "api/test_post", $options)
If I look the request content on the receiving end, nothing is there. No field or file.
I've seen couples posts, some say to include headers some say not too. I kinda got lost and amd now running out of ideas.
I would expecet the infos to be as if they where form post I guess:
$request->inpust('field_1') -> 'test'
$request->inpust('field_2') -> 'test'
$request->inpust('field_3') -> 'test'
$request->file('file') -> my uploaded file
Also I should point out that I am not exactly sure how multipart/form-data works, so that might not help me.
If you can point me to the right direction, that would help a lot
Well I finally figured it out. The second example from above is the way to go also be sure to check the headers of the request and the client...
As this API has been running for quite some time and was only doing json type requests, the Client was instantiated with
$options = [
headers => [ 'Content-Type' => 'application/json']
]
Which, as stated in multiple answers across the internet, prevents Guzzle to automatically set the Content-Type depending of the request options.
In my case, removing this line made Guzzle enable to set it properly when provided with 'multipart' option.
Also, as all other requests are using the 'json' options, Guzzle also works it's magic and set 'Content-Type' => 'application/json' as well.
I have used "JWT Authentication for WP-API" plugin to login and to generate a token.
On the JSON response I have only some data from the wp_users table.
How can I change it to take some others value from wp_usermeta table on response, because I want to know user status level.
You need to use the filters jwt_auth_token_before_sign or jwt_auth_token_before_dispatch.
The first filter receives the token data, and a user object.
In another plugin or in your theme, you'd need to call add_filter.
I'm a bit rusty on my Wordpress, and I do not have a WP instance handy to test this out, but this is the general theory:
Basic example:
add_filter('jwt_auth_token_before_sign', 'add_user_info_jwt', 10, 2);
function add_user_info_jwt($token, $user) {
// fetch whatever information you want from the user, probably using the $user
// object as starting point.
$token['roles'] = implode(',', $user->roles);;
return $token;
}
The $token you receive will have this starting structure and information:
$token = [
'iss' => get_bloginfo( 'url' ),
'iat' => $issuedAt,
'nbf' => $notBefore,
'exp' => $expire,
'data' => [
'user' => [
'id' => $user->data->ID,
]
]
];
I have a request class that fails for a post request. When I call it with ajax I get an 422 because the validation rules failed. But when I use phpunit for test for the same route with same values, it returns a 302.
I also get no error messages like "field foobar is required" just the 302.
So how can I get the error messages to check if they are equals or not?
Here is my testcode:
//post exam
$this->post('modul/foo/exam', [
'date' => '2016-01-01'
])
->assertResponseStatus(200);
//post exam again
$this->post('modul/foo/exam', [
'date' => '2016-01-01'
])
->assertResponseStatus(302); //need to get 422 with th errors because its an api
When the validation on the FormRequest fails, it checks to see if the request was ajax or if it accepts a json response. If so, it will return a json response with the 422 status code. If not, it will return a redirect to a specified url (previous, by default). So, in order to get the response on failure you're looking for (422), you need to make a json request or an ajax request.
JSON
To make a json request, you should use the json() method:
//post exam
$this->json('POST', 'modul/foo/exam', [
'date' => '2016-01-01'
])
->assertResponseStatus(200);
//post exam again
$this->json('POST', 'modul/foo/exam', [
'date' => 'some invalid date'
])
->assertResponseStatus(422);
There are also getJson(), postJson(), putJson(), patchJson(), and deleteJson() shortcut methods if you think that looks cleaner than passing the method as a parameter.
//post exam
$this->postJson('modul/foo/exam', [
'date' => '2016-01-01'
])
->assertResponseStatus(200);
AJAX
To make an ajax request, you need to add in the ajax headers. For this, you can continue to use the post() method:
//post exam
$this->post('modul/foo/exam', [
'date' => '2016-01-01'
], ['HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'])
->assertResponseStatus(200);
//post exam again
$this->post('modul/foo/exam', [
'date' => 'some invalid date'
], ['HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'])
->assertResponseStatus(422);
For Laravel 6 this works:
withHeaders(['Accept' => 'application/json'])
For an example:
$this->withHeaders(['Accept' => 'application/json'])
->post(route('user.register'), $data)
->assertStatus(422)
->assertJson($expectedResponse);
If it's needed for multiple test classes, it can be placed in tests/TestCase.php and it will be set up for all test cases.
For an example:
public function setup(): void
{
$this->withHeaders([
'Accept' => 'application/json',
'X-Requested-With' => 'XMLHttpRequest'
]);
}
Those headers set in tests/TestCase.php can be extended at any point by the same way. For an example:
$this->withHeaders([
'Authorization' => 'Bearer '.$responseArray['access_token']
]);