LswApiCallerBundle POST data - symfony

I want to make a call to this API: https://api.airbnb.com/v2/search_results, using Symfony2 and LswApiCallerBundle.
Following the instructions I make the call using this code:
$url = 'https://api.airbnb.com/v2/search_results';
$data = [
'client_id' => '3092nxybyb0otqw18e8nh5nty',
];
$output = $this->get('api_caller')->call(new HttpGetJson($url, $data));
As a result I get this:
Status: 0 Connection failed URL:
https://api.airbnb.com/v2/search_results Type:
Lsw\ApiCallerBundle\Call\HttpGetJson Request: 35 bytes raw html parsed
Response: 0 bytes raw html parsed Time: 62.89 ms
With a "null" response. Can someone tell me please where I'm failing or if there is another way of doing it?
Thanks

I found a solution, substituting Lsw Bundle for Guzzle one(https://github.com/LeaseWeb/LswGuzzleBundle).
Follow the documentation to configure it.

Related

lumen - Why does PHPUnit register test returns 405?

I want to make phpunit tests for lumen app, like :
public function testRegisterUser()
{
$newUserData = [
'name' => 'test_user',
'email' => 'test_user#mail.com',
'password' => Hash::make('111111'),
'status' => 'A',
'has_debts' => false
];
$response = $this->get('/api/v1/register', $newUserData); // http://localhost:8000/api/v1/register
$this->assertResponseOk();
}
But running tests I got 405 error :
1) PagesTest::testRegisterUser
Expected response status code [200] but received 405.
Failed asserting that 200 is identical to 405.
/ProjectPath/vendor/illuminate/testing/TestResponse.php:177
/ProjectPath/vendor/illuminate/testing/TestResponse.php:99
/ProjectPath/vendor/laravel/lumen-framework/src/Testing/Concerns/MakesHttpRequests.php:415
/ProjectPath/tests/PagesTest.php:27
Why I got 405 Method Not Allowed ? I postman I check my method : https://prnt.sc/207bu03
Method /api/v1/register in postman has no any token protection.
How to make my test working ?
UPDATED BLOCK :
I got error :
Error: Call to undefined method PagesTest::getJson()
If I modify :
$response = $this->getJson('/api/v1/register', $newUserData);
method getJson is mentioned here : https://laravel.com/docs/8.x/http-tests
But on this page I see in test file header:
namespace Tests\Feature;
But not in my generated lumen test file.
In my routes/web.php I have :
$router->group(['prefix'=>'api/v1'], function() use($router){
$router->post('/register','AuthController#register');
$router->post('/login', 'AuthController#login');
$router->group(['middleware' => 'auth'], function () use ($router) {
$router->get('/profile', 'UserProfileController#index');
What is wrong ?
Thanks!
Because you maybe have to use $this->getJson instead of $this->get.
It is not http://localhost:8000 as you are testing, you are not literally accessing the URL. It is simulating that.
Also share your api.php or routes file and the controller please (also the middlewares working on that URL).
Looking at the Lumen's documentation I can see that there is no getJson, my bad. You have to use $this->json('GET' instead.

Elixir HttpPoison not working to send multipart/form-data requests

I have a very simple request to make but it looks like HttpPoison isn't able to resolve this.
The request has attachments, so i'm using multipart/form-data content type.
When I send just the file, the request works fine, but I need to add some other props to my request and that's where the issue comes.
My request:
HTTPoison.post(
"path.com/api/anything",
{:multipart, [
{
:file,
"/path/file.xlsx",
{"form-data", [name: "file", filename: "file.xlsx"]}, []
},
{"taskName", "#{task.name}"},
{"taskLink", "#{task.link}"}
]},
)
I receive the file without problems but the taskName and taskLink never reach the server.
( I tried with postman and had no problems )
Some issues related to this:
https://elixirforum.com/t/httpoison-post-multipart-with-more-form-than-the-file/4222/4
https://github.com/edgurgel/httpoison/issues/237
We have a working example of the multipart list that we use to send zip files along with other attributes. Something equivalent to this might work for you.
[
{"id", to_string(order_id)},
{"file_size", to_string(file_size)},
{"attachment", file, {"form-data", [name: "file", filename: filename]},
[{"Content-Type", "application/zip"}]
}
]

Get current user inside register_rest_route method

How to retrive wp_get_current_user() inside a register_rest_route callback (Wordpress site)?
I'm just trying to do a simple hello wp_get_current_user()->user_login on a php test page:
add_action('rest_api_init', 'helloTest');
function helloTest() {
register_rest_route('hello', 'hello/(?P<id>\d+)', array(
'methods' => WP_REST_SERVER::READABLE,
'callback' => 'showHello'
));
}
function showHello($someVariable) {
echo "Hello " . wp_get_current_user()->user_login . $someVariable;
}
But wp_get_current_user() is null and wp_get_current_user->ID is 0;
I dont want to authenticate the user again. I just want to retrieve his username. If he is not logged in, just show empty an empty string.
If I have to authenticate again, how to add a "nonce" to it? On internet I just have examples using javascript, but not directly on PHP methods.
Issues in your code
First off, you should understand properly how to add custom WP REST API endpoints:
An endpoint's namespace (the first parameter passed to register_rest_route()) should be in this format: your-plugin/v<version>. E.g. hello/v1 or hello-world/v1 and not just hello or hello-world.
$someVariable (the first parameter passed to your endpoint callback function) is not just any variable — it's an instance of the WP_REST_Request class — and shouldn't be echo-ed like what you did here:
function showHello($someVariable) {
echo "Hello " . wp_get_current_user()->user_login . $someVariable;
}
And normally, the $someVariable is better be changed to $request (i.e. rename it to "request").
And you should return a valid WP REST API response. For example, to return just the username:
return new WP_REST_Response( wp_get_current_user()->user_login, 200 );
And know your own API endpoint URL..
(based on your original namespace)
/wp-json/hello/hello/1 <- correct
/wp-json/hello/?John <- incorrect
because in your code, the parameter is a number and not string: (?P<id>\d+)
I hope those help you, and once again, do read the handbook for a more detailed guide.
The Corrected Code
add_action( 'rest_api_init', 'helloTest' );
function helloTest() {
register_rest_route( 'hello/v1', 'hello/(?P<id>\d+)', array(
'methods' => WP_REST_SERVER::READABLE,
'callback' => 'showHello'
) );
}
function showHello( $request ) {
return new WP_REST_Response( wp_get_current_user()->user_login, 200 );
}
Now about getting the user (from the API endpoint — showHello())
If I have to authenticate again, how to add a "nonce" to it?
Just because the user is logged-in/authenticated to the (WordPress) site, it doesn't mean the user is automatically logged-in to the WP REST API. So yes, you'd need to either provide a nonce along with your API request, or use one of the authentication plugins mentioned right here.
Now in most cases, GET (i.e. read-only) requests to the API do not need any authentication, but if you'd like to retrieve the data of the currently logged-in user on your site, then one way is via the _wpnonce data parameter (either POST data or in the query for GET requests).
Example for a GET request:
http://example.com/wp-json/wp/v2/posts?_wpnonce=<nonce>
So based on your comment and the corrected code (above):
Theres no "code" that make the request. Its is just an anchor that
calls my route: Hello
You can add the nonce as part of the URL query string like so: (the namespace is hello/v1 and the <id> is 1)
// Make request to /wp-json/hello/v1/hello/<id>
$nonce = wp_create_nonce( 'wp_rest' );
echo 'Hello';
So try that out along with the corrected code and let me know how it goes. :)
And once again, be sure to read the REST API authentication handbook.

Fetch - sending POST data

My PHP script isn't receiving anything via POST from fetch. What am I doing wrong?
Javascript:
fetch("http://127.0.0.1/script.php", {
method: "post",
body: "inputs=" + JSON.stringify({param: 7})
}).then(response => response.json()).then(response => {
console.log(response);
});
script.php:
echo "\nprinting POST:\n";
print_r($_POST);
echo "\nprinting GET:\n";
print_r($_GET);
die();
Console:
printing POST: Array ( )
printing GET: Array ( )
You're not adding any url parameters (hence $_GET is empty) and you're not setting a Content-Type header that will make PHP automatically parse the request body. (hence $_POST is empty).
There was something wrong with the htaccess file for that particular test PHP file. I've used it for posting something to the main project folder/PHP files and it went ok.

HTTP client Cakephp 3 ignores json body

I'm currently writing a RESTful API in Cakephp 3 whereby I need to test a POST operation through http://host.com/api/pictures. The code for the test:
<?php
namespace App\Test\TestCase\Controller;
use App\Controller\Api\UsersController;
use Cake\TestSuite\IntegrationTestCase;
use Cake\Network\Http\Client;
use Cake\Network\Http\FormData;
class ApiPicturesControllerTest extends IntegrationTestCase{
public $fixtures = [
'app.users',
'app.comments',
'app.albums',
'app.users_albums'
];
public function testAdd(){
// $data = new FormData();
$accessToken ='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjksImV4cCI6MTQ1NzYyOTU3NH0.NnjXWEQCno3PUiwHhnUCBjiknR-NlmT42oPLA5KhuYo';
$http = new Client([
'headers' => ['Authorization' => 'Bearer ' . $accessToken, 'Content-Type' => 'application/json']
]);
$data = [
"album_id" => 1,
"link" => "http://www.google.com",
"description" => "testtesttest",
"favorite" => true
];
$result = $http->post('http://vecto.app/api/pictures/add.json', $data, ['type'=>'json']);
// $this->assertResponseOk();
// debug($result);
}
}
When I try to debug the result I get a 'cannot add or update child row' while I'm sure the responding id does exists
(the fixtures does have the id's too). Additionally, the log indicates that it only tries to insert the create/update rows. Therefore, I'm pretty sure the data is ignored but however I can't find a solution. I already tried different combination of headers like only application/json for Accept, application/json for Content-Type etc. I'm using the CRUD plugin for Cakephp to pass the data to an add function.
Postman output
Furthermore, I tried the Postman Chrome plugin to save the data and that actually does work. Does anyone know what I'm doing wrong in the test?
That's not how the integration test case is ment to be used. You are dispatching an external, real request, which will leave the test environment, while you should use the request dispatching tools that the integration test case supplies, that is
IntegrationTestCase::get()
IntegrationTestCase::post()
IntegrationTestCase::put()
etc...
These methods will dispatch simulated requests that do not leave the test environment, which is crucial for things to work properly, as you want to use test connections, inspect possible exceptions, have access to the used session, etc...
ie, you should do something along the lines of
$accessToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjksImV4cCI6MTQ1NzYyOTU3NH0.NnjXWEQCno3PUiwHhnUCBjiknR-NlmT42oPLA5KhuYo';
$this->configRequest([
'headers' => [
'Authorization' => 'Bearer ' . $accessToken,
'Content-Type' => 'application/json'
]
]);
$data = [
"album_id" => 1,
"link" => "http://www.google.com",
"description" => "testtesttest",
"favorite" => true
];
$this->post('/api/pictures/add.json', json_encode($data));
Note that a content type of application/json will require you to send raw JSON data! If you don't actually need/want to test parsing of raw input, then you could skip that header, and pass the array as data instead.
See also
Cookbook > Testing > Controller Integration Testing
API > \Cake\TestSuite\IntegrationTestCase

Resources