HTTPS: 400 Bad request! Invalid JSON - json

I am trying to pass a POST method request for a specific URI using the Restclient gem. I am however, continously getting 400 Bad request from the server. I have tried numerous ways of posting the data, with modifications. PFB the current one
require 'minitest'
require 'rest-client'
require 'json'
require 'pry'
require 'uri/https'
#class APITest < Minitest::Test
def setup
response = RestClient.post("", {'userType' => 'nonsso', 'firstName' => 'Justin9', 'isDependentMajor' => true, 'email' => 'randomemail0053#gmail.com', 'dependentName'=> 'Cobb', 'dependentLastName' => 'Cobb', 'lastName' => 'Justin'
}, { "Content-Type" => 'application/json'})
puts response
end
setup
I am at a loss to understand what am I missing here. I tried using the same code, for an other api, with get method, only with headers and it works.
Please can someone let me know, any bad syntax in json I am using for the POST method.

response = RestClient.post("", {'userType' => 'nonsso', 'firstName' => 'Justin9', 'isDependentMajor' => true, 'email' => 'randomemail0053#gmail.com', 'dependentName'=> 'Cobb', 'dependentLastName' => 'Cobb', 'lastName' => 'Justin'
}.to_json, { "Content-Type" => 'application/json'})
Note the to_json.
RestClient serializes the payload in application/x-www-form-urlencoded by default. You have to manually serialize your post data.

Related

return errors while using API routes in Laravel 8

I'm building a small application to store contacts in the database, I've finished the GET/POST routes, and worked fine, now I'm on the API routes (in order to use AJAX calls). I can store the information if all fields are present in the POST request, nonetheless, If I want to send messages back to the call (to send feedback about why the contact hasn't been stored) the response is sending me to the main route www.myapp.com (with no messages) and I want to send a json back with the "reason".
At this moment I only validate if the 'nombre', 'correo', 'telefono' have information with standard Laravel's request validate method.
This is my LeadController
public function storeApi(Request $request)
{
$request -> validate([
'nombre' => 'required',
'correo' => 'required' ,
'telefono' => 'required'
]);
if(Lead::create($request->all())){
$result[] = ['saved' => true];
}else{
$result[] = ['saved' => false,
'reason' => 'Some data is missing'];
return response()-> json($result);
};
return response()-> json($result);
}
When the record is stored, it does send back the Json {'saved' : true} but when fails It just sends you back to the '/' Route: www.myapp.com
How can I send the messages back to the POST call?
It is redirecting back to "/" because $request->validate() method throws \Illuminate\Validation\ValidationException exception..
There are try ways to handle this request.
Put try catch block around your validate code
Or Handle this expection in app\Exception\Handler.php, and return the response in JSON format.
After some further reading I just change the way the information is validated using the Validator Class:
public function storeApi(Request $request)
{
$validator = \Validator::make($request->all(), ['nombre' => 'required', 'correo' => 'required', 'telefono' => 'required']);
if($validator->fails()){
return response()->json($validator->errors(), 422);
}else {
//ready to store
}
}
This way I don't let the ValidationException exception occurs before sending the feedback to the call.

Can't post JSON data to GitHub API (and probably others)

I'm using HTTP::UserAgent to try and use GitHub API from a program. Here's the program
use HTTP::UserAgent;
my $greeting = (%*ENV<BODY> ~~ /[Mm]erry/)??%*ENV<GREETING>!!%*ENV<HEY>;
my $url = "https://api.github.com/repos/JJ/raku-advent-calendar-article-2019/issues/%*ENV<ISSUE>/comments";
my %headers = Authorization => "token %*ENV<TOKEN>" ;
my %payload = body => $greeting;
my $agent = HTTP::UserAgent.new( useragent => "JJ's Xmas commenter" );
say $agent.post( $url, %payload,
Authorization => "token %*ENV<TOKEN>",
Content-Type => "application/json" );
If the content-type is not established, there's a malformed JSON error. If it's used, however, the error is different: 422 Unprocessable Entity. When using curl or similar, you can usually post directly the JSON string, but post in this case does not admit single strings, or if it's a form, I have no idea what to use as key. Can you please help?

Axios | VueJS | Laravel | Post Request Not able to access Object

So I'm attempting to send my post data to my controller and then access it via a object. It definitely passes the data but for some reason wont let me access any of the items with in that object its really weird.
Here is my post request in the vue component.
axios.post('/users', {user: this.user})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error.response)
});
Here is what I have in my controller and as I said I do get the user info but I cant access it such as doing $user->id, but when I just do $user I can see the user data including the id.
//Here we get all the users info from the Axios Vue.
$user = $request->get('user');
return response()->json([
'status' => 'success',
'msg' => $user->id,
], 201);
The error I get is a php error as I can is it under the network response area and this is what the error message says.
"message": "Trying to get property 'id' of non-object"
But when I just do this in the controller.
//Here we get all the users info from the Axios Vue.
$user = $request->get('user');
return response()->json([
'status' => 'success',
'msg' => $user,
], 201);
It returns a 201 and shows this in the msg.
{"id":1,"email":"test#test.com","full_name":"John Doe","first_name":"John","last_name":"Doe","is_active":1,"overide_login":1,"skill_id":5,"phone":null,"shifts_id":0,"bilingual":0,"full_time":0}
Am I formatting the Object wrong or something?... It would be great if someone could help because I really don't understand why this does not work.
ALSO NOTE EVERYTHING IS ON THE NEWEST RELEASES OF VUEJS/AXIOS AND LARAVEL.
You have to decode it first, please add this into your controller.
$input = ($request->all() == null ? json_decode($request->getContent(), true) : $request->all());
echo $input['user']['id']
Hope this works for you.

Return JSON based on "Accept: application/json" from a Symfony2 controller

I've got a CRUD form generated via the SensioGeneratorBundle, as described here. This works great.
However, I would like to also return JSON, rather than HTML responses, if the "Accept" HTTP header contains only "application/json". I'm working on a prototype for a JSON service and this would help me jump start things.
I figured out that I can turn my entities into a JSON string like this:
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
$serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new
JsonEncoder()));
$json = $serializer->serialize($entity, 'json');
However, at the end of that, $json contains a string that is my JSON data. I want to just directly output that to the requestor, rather than render the usual view. I've tried returning a new JsonResponse($json), but it re-encodes the JSON string, so it winds up double-encoded.
So I have two questions:
What is the "correct" way to inspect the HTTP requestion headers? I know I can just look in $_SERVER, but I'm thinking that there may be a better way to do this in Symfony2.
What is the "correct" way to return a JSON string, or to translate my entities into JSON that is returned straight to the requestor, without rendering the usual view.
Thanks!
This will verify if the current request is XHR and then send back properly formatted JSON data:
public function someAction(Request $request)
{
if ($request->isXmlHttpRequest()) {
$serializer = new Serializer(array(
new GetSetMethodNormalizer()
), array(
'json' => new JsonEncoder()
));
$response = $serializer->serialize(array(
'success' => true,
'data' => array(
'entity' => $entities,
)
), 'json');
return new Response($response, 200, array('Content-Type' => 'application/json'));
} else {
// Run "normal" request code, render a view
}
}
By the way, JMSSerializerBundle makes the serializing syntax more straightforward (because, let's face it, the native Symfony way for this is ugly) and also provides some additionnal features such as excluding entity fields to serialize (through annotations).
With JMS, my code looks like this:
if ($request->isXmlHttpRequest()) {
$response = array('success' => true, 'data' => array(
'entity' => $this->container->get('serializer')->serialize($entity, 'json'),
'lastPage' => $lastPage,
));
return new Response(json_encode($response), 200, array('Content-Type' => 'application/json'));
}
And finally, 'success' and 'data' are in no way required, it's just the structure I use to split status and data to be readable in JavaScript.

getting csrf tokens for json post requests to a rails app

I have been playing around with using rest-client to access a rails app I have written. I've written a quick script to log in and make a post request. Everything is working but I did have to work round the fact that no authenticity_token is served if you make a request for a form in json. I had to make a regular html request in other get the authenticity_token and then included this in the json I submitted as part of my post request. Basically I have a quick an dirty script like the one below
private_resource = RestClient::Resource.new( 'https://mysite.com')
params = {:user => {:email => 'user#mysite.com', :password => 'please'}}
#log in
login_response = private_resource['users/sign_in'].post(params, :content_type => :json, :accept => :json)
#get cookie
cookie = login_response.cookies
#get json
json_response = private_resource['products/new'].get(:content_type => :json, :accept => :json, :cookies => cookie)
#another request that returns html form with authenticity token
response_with_token = private_resource['products/new'].get( :cookies => cookie)
#extract token
token = Nokogiri::XML(response_with_token).css('input[name=authenticity_token]').first.attr('value')
#update cookie
cookie = response_with_token.cookies
#populate form and insert token
form = JSON.parse(json_response)
form['name'] = "my product"
form['authenticity_token'] = token
#submit the request
private_resource['products'].post(form.to_json, {:cookies => cookie, :content_type => :json, :accept => :json})
There is the option to turn off CSRF protection for json requests but I would rather not do that. I could go the mechanize route or something similar and then I wouldn't worry about json requests with CSRF but I just wanted to play around with doing this stuff with rest-client
I guess I'm just curious to know if there is a reason why no authenticity_token is served for json requests and I'm also wondering if there is a better way of solving the token problem than the pretty hacky approach I've taken here
Put the below code into your application controller :
def verified_request?
if request.content_type == "application/json"
true
else
super()
end
end
And call this method using before_filter .
For more details check :
http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html
And check this issue in rails : https://github.com/rails/rails/issues/3041
In your app/views/products/new.json.jbuilder, add this:
json.authenticity_token form_authenticity_token
This will insert a key "authenticity_token" with value being the token, so in your json_response you get the token as well. Idea from this answer.