Guzzle not returning body resulting in $request->getBody() not providing the addFile() function - guzzle

I've included 'https://github.com/guzzle/guzzle/releases/download/5.2.0/guzzle.phar' using require 'guzzle.phar';
I've then added
$client = new Guzzle\Http\Client();
$request = $client->createRequest("POST", <URL>);
$postBody = $request->getBody();
$postBody->addFile(new PostFile('file', fopen('#./images'.$location, 'r')));
$response = $client->send($request);
$body = $response->json();
return $body['id'];
But I get
Error: Call to a member function addFile() on null
What is causing this?

To fully understand your error we must look at the source code for the Request::__construct(), AbstractMessage::getBody(), and Request::handleOptions() methods.
As you can see, if the request is instantiated without the 'body' option, it will be set to null. So, when you call $request->getBody() you receive NULL instead of a MessageInterface instance.

Related

RestAssured response validation using body and array as parameter

I am trying to validate a REST response. Is it possible to use an array as parameter to containsonly?
Ex:
String values[] = line.split(",");
given().
when().
then().
statusCode(200).
body("value", containsOnly(values));
Also, can we use variables as parameters to other methods like HasItems, equalTo etc?
Ex: body(HasItems(values))
Yes, You could use any appropriate matcher to check whole body or just part of it. Just take attention on a object type returned by pecified path - first argument of body().
Try this :
Response resp = RestAssured.given()
.header("Content-Type", "application/vnd.dpd.public.v1+json")
.body(FixtureHelpers.fixture("request/request.json"))
.post("/");
resp
.then()
.statusCode(200)
.body("random.object", CoreMatchers.equalTo("value"));
This would work for request.json object like :
{"random":{"object": "value"}}

Slim 3 - how to get all get/ put/ post variables?

How I can get all get/ put/ post variables like in Slim 2 for Slim 3?
Slim 2,
$allGetVars = $app->request->get();
$allPutVars = $app->request->put();
$allPostVars = $app->request->post();
How can I do that in Slim 3?
And, for example, http://example.com/books/1?title=hello&content=world
How can I get the params in title and content in Slim 3 now?
Slim 2,
$title = $app->request->get('title');
$content = $app->request->get('content');
How can I do that in Slim 3?
Get all get/put/post parameters:
//GET
$allGetVars = $request->getQueryParams();
foreach($allGetVars as $key => $param){
//GET parameters list
}
//POST or PUT
$allPostPutVars = $request->getParsedBody();
foreach($allPostPutVars as $key => $param){
//POST or PUT parameters list
}
Single parameters value:
//Single GET parameter
$getParam = $allGetVars['title'];
//Single POST/PUT parameter
$postParam = $allPostPutVars['postParam'];
To Get all request params:
$request->getParams()
Request Uri: getQueryParams()
Request Body: getBody()/getParsedBody()
It's not exactly what you are looking for but it comes pretty close.
You can use the map() method to combine get, post & put into a single route.
$app->map(['GET', 'POST', 'PUT'], function(Request $request, Response $response, array $args)) { }
The first argument is an array of the HTTP methods that you want to match. The second parameter is the function that handles the request; pass a request, response and an array of arguments.

In a REST API, to GET a resource, should I include the resource ID in the url?

I am trying to create an REST API for creating and retrieving files in my database. The tutorial I was following uses the following method to retrive a single file:
$app->get('/file/:file_id', 'authenticate', function($file_id) {
global $user_id;
$response = array();
$db = new DbHandler();
// fetch file
$result = $db->getFile($file_id, $user_id);
if ($result != NULL) {
$response["error"] = false;
$response["id"] = $result["id"];
$response["file"] = $result["fileLocation"];
$response["status"] = $result["status"];
$response["createdAt"] = $result["created_at"];
echoRespnse(200, $response);
} else {
$response["error"] = true;
$response["message"] = "The requested resource doesn't exist";
echoRespnse(404, $response);
}
});
Here they are using the HTTP GET method and are specifying the file ID in the URL, is it OK to do this, safety wise? Would it not be safer to use POST and hide the file ID in the body of the request, or should they not be putting the file ID in a header with the GET request? or is it not something I should be worried about?
In REST post method is used to create a new resource not to get it. Get method is used for fetching the resource and you need to specify the ID to determine particular resource. Passing it via URL is a common practice. You can randomly generate such ID to make it harder to guess.
As Opal said above, the ID is used to identify a resource. If you are unsure have a read of this - http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post

How to test form request rules in Laravel 5?

I created a form request class and defined a bunch of rules. Now I would like to test these rules to see if the behaviour meets our expectations.
How could I write a test to accomplish that?
Many thanks in advance for your answers!
Update: more precisely, I would like to write a unit test that would check e.g. if a badly formatted email passes validation or not. The problem is that I don't know how to create a new instance of the Request with fake input in it.
The accepted answer tests both authorization and validation simultaneously. If you want to test these function separately then you can do this:
test rules():
$attributes = ['aa' => 'asd'];
$request = new MyRequest();
$rules = $request->rules();
$validator = Validator::make($attributes, $rules);
$fails = $validator->fails();
$this->assertEquals(false, $fails);
test authorize():
$user = factory(User::class)->create();
$this->actingAs($user);
$request = new MyRequest();
$request->setContainer($this->app);
$attributes = ['aa' => 'asd'];
$request->initialize([], $attributes);
$this->app->instance('request', $request);
$authorized = $request->authorize();
$this->assertEquals(true, $authorized);
You should create some helper methods in base class to keep the tests DRY.
You need to have your form request class in the controller function, for example
public function store(MyRequest $request)
Now create HTML form and try to fill it with different values. If validation fails then you will get messages in session, if it succeeds then you get into the controller function.
When Unit testing then call the url and add the values for testing as array. Laravel doc says it can be done as
$response = $this->call($method, $uri, $parameters, $cookies, $files, $server, $content);
Here's a full example of testing validation:
use App\Http\Requests\PostRequest;
use Illuminate\Routing\Redirector;
use Illuminate\Validation\ValidationException;
class PostRequestTest extends TestCase
{
protected function newTestRequest($data = [])
{
$request = new PostRequest();
$request->initialize($data);
return $request
->setContainer($this->app)
->setRedirector($this->app->make(Redirector::class));
}
public function testValidationFailsWhenEmptyTitleIsGiven()
{
$this->expectException(ValidationException::class);
$this->newTestRequest(['title' => ''])->validateWhenResolved();
}
}

ZF2 JSON-RPC - Error response, data parameter, how to access?

Let's say I have an RPC call for adding colors. A user can only add colors once. If they add one a second time, I want to return an error response that tells them they screwed up, and why.
The JSON-RPC error response describes an error object that includes a space for a data parameter. It is in here that it seems appropriate to include my error code for "color already added". However, I cannot figure out how to return this in the response.
$jsonRpc = new Server();
$jsonRpc->setClass(new Testi());
$jsonRpc->getRequest()->setVersion(Server::VERSION_2);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
echo $jsonRpc->getServiceMap()->setEnvelope(Smd::ENV_JSONRPC_2);
}
else {
$jsonRpc->handle();
}
class Testi {
const ERROR_CODE_COLOR_EXISTS = 5;
private $colors = ['red', 'green'];
/**
* #param $color
* #return array
*/
public function addColor($color) {
if (in_array($color, $this->colors)) {
throw new \Exception('Color exists');
}
else {
$this->colors[] = $color;
}
return $this->colors;
}
}
This works, to the degree that an error response is returned, but gives me no option to include my error code (self::ERROR_CODE_COLOR_EXISTS).
{"error":{"code":-32000,"message":"Color exists","data":{}},"id":"","jsonrpc":"2.0"}
How do I put info into that DATA parameter!?
Thanks,
Adam
Turns out you have two choices to do this:
1) Add parameters to an exception:
$e = new Exception('I pooped my pants');
$e->color = 'brown';
$->smell = 'bad';
color and smell would then be in the data parameter of the error response.
2) Pass the server (in my code, $jsonRpc) into the object (in my code, it would look something like: new Testi($jsonRpc)), and use the fault(...) method, which allows you to pass the data array/object into it.
The latter approach gives you more flexibility as you can do data->code, data->message, neither of which can you set on the $e object, because they are existing, protected parameters. But you are then coupling your model to the $jsonRpc server, which is not good.
All that being said, it's not the correct way to respond to the scenario I outlined above. The error response is more or less reserved for true, unrecoverable server errors, akin to real exceptions, not user validation errors. In my case it was better to define a response type that allows me to return success/fail values with appropriate response codes. {success: false, code: 5}.
Cheers,
Adam