Laravel response status code set to 400 but browser reports 200 - backbone.js

I'm trying to return a 400 status code from Laravel. I've setup a simple test in my controller:
return Response::json(["Test", "Array"], 400);
And look at web inspector I get a 200 OK.
If I dump the response:
object(Illuminate\Http\JsonResponse)#306 (8) {
["data":protected]=>
string(16) "["Test","Array"]"
["callback":protected]=>
NULL
["headers"]=>
object(Symfony\Component\HttpFoundation\ResponseHeaderBag)#315 (5) {
["computedCacheControl":protected]=>
array(1) {
["no-cache"]=>
bool(true)
}
["cookies":protected]=>
array(0) {
}
["headerNames":protected]=>
array(3) {
["cache-control"]=>
string(13) "Cache-Control"
["date"]=>
string(4) "Date"
["content-type"]=>
string(12) "Content-Type"
}
["headers":protected]=>
array(3) {
["cache-control"]=>
array(1) {
[0]=>
string(8) "no-cache"
}
["date"]=>
array(1) {
[0]=>
string(29) "Wed, 02 Apr 2014 20:03:14 GMT"
}
["content-type"]=>
array(1) {
[0]=>
string(16) "application/json"
}
}
["cacheControl":protected]=>
array(0) {
}
}
["content":protected]=>
string(16) "["Test","Array"]"
["version":protected]=>
string(3) "1.0"
["statusCode":protected]=>
int(400)
["statusText":protected]=>
string(11) "Bad Request"
["charset":protected]=>
NULL
}
I can see that the status code is set to 400 and the statusText is Bad Request.
Basically I'm using Backbone.js in conjunction with Laravel and need to return a status code other than 200 to catch errors on save.
This seems like such a simple thing to do, does anyone know what I'm having this issue?
UPDATE
After some head bashing I've found a (not very ideal) work around to achieve what I need, and logged a issue on the Laravel GitHub: https://github.com/laravel/laravel/issues/2796
Basically I took my controller out of the equation and tried this as a route:
Route::get('/bad-request', function() {
$response['state'] = "error";
$response['errors'] = ["name" => ["A product name is required"]];
return Response::json($response, 400);
});
Same issue, returns a 200. Found this work around for the time being:
Route::get('/bad-request', function() {
$response['state'] = "error";
$response['errors'] = ["name" => ["A product name is required"]];
http_response_code(400);
return Response::json($response, 400);
});
I'd much rather do this with Laravel than forcing it with PHP. Also I've tried Response::make and that does exactly the same thing.

I ran into this problem myself recently, it should work but for some reason it doesn't. You need to make the response object yourself.
Response::make(["Test", "Array"], 400);
This will still return the array as JSON automatically for some reason...

this worked for me:
new Response(Array,400); //will return 400
although the api will tell you otherwise, this is not working:
new Response()->json(Array,400); // will return 200
new Response()->make(Array,400); // will return 200

Related

Angular2 - send object in http.post request body

I am working on Angular2 web project, in my ts class I have an object :
Object: any= {
"first":null,
"second":null,
"third": null,
}
I want to send the object in http.post request body. I tried the next code, but it doesnot work;
method() {
const url='/pathname/';
return this.http.post(url, this.Object).pipe(map((data:any)=>data));
}
I got an error in console:
error : HttpErrorResponse {headers: HttpHeaders, status: 400, statusText: "OK",url: "http://localhost:8080/path", ok: false,..}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure response for
http://localhost:8080/path 400 OK"
name: "HttpErrorResponse"
ok: false
status: 400
statusText: "OK"
url: "http://localhost:8080/path"
Can you explain me how to send typescript object in post request body ? Thank you in advance
You need to subscribe to the post observable returned by method function. It is done like this.
this.method().subscribe(
res => {
// Handle success response here
},
err => {
// Handle error response here
}
);
you should subscribe the post method because this method of http class returns a observable.
you can rewrite your code as:-
method() {
const url='/pathname/';
return this.http.post(url, this.Object).subscribe( resp=> {
const data = resp; // response you get from serve
}, error => {
console.log(error); //error you get from server
});
}
you are getting the 400 bad request error, the payload keys are mis matching with the middle wear. please suggest pass the correct params into Request object.

getting Network Error when calling axios get request in react js

I am using React.js in macOS and when I try to call axios.get, I get Network Error. I read many other cases like mine who were using React Native and the answer to them was adding settings to allow them to use http in mac instead of https, but that setting can not be used in react js.
Any advice would be appreciated.
Error: Network Error
at createError (createError.js:17)
at XMLHttpRequest.handleError (xhr.js:87)
My code is like this:
try {
const Response = await axios.get(http://xxxxx/WebServiceTest/service.svc?wsdl/GetItems, {
params: {
Number: "100",
Id: "101",
userName: "11",
credential: "Test"
}
});
console.log("http response = " + Response.data);
} catch (ex) {
console.log("error.status:", ex);
}
Change your await to a promise, even if you put await the axios function will work asynchronously.
async functionName() {
let response = () => {
return new Promise(function(resolve, reject) {
fetch('http://xxxxx/WebServiceTest/service.svc?wsdl/GetItems', {
params: {
Number: "100",
Id: "101",
userName: "11",
credential: "Test"
}
}).then(response => {
resolve(response);
});
});
};
let responseData = await response();
console.log(responseData.data);
}
You can simply make the following changes in your
axios.create({baseURL:" "});
make it into
const instance = axios.create(
{
baseURL: "",
withCredentials: false,
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
}
})
In your case try adding the above wherever you must have created instance of your axios.If you are using default axios then consider creating custom instance following the above code.
I have found the solution in spring boot by using #CrossOrigin annotation.
#RestController
#CrossOrigin
#RequestMapping("/cus")
public class CusController{
#Autowired
CustomerService cus_service=null;
#PostMapping("/save")
public Customer saveCustomer(#RequestBody Customer customer)
{
if(customer!=null)
return cus_service.saveCustomer(customer);
else
throw new DataNotFoundException("Data Not Available For Customer");
}
}
You can use axios method in reactjs using some commands on server side code to get rid of cors policy error
i have used these commands on my server side code which is in php
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: *');
header('Access-Control-Max-Age: 1728000');
header("Content-Length: 0");
header("Content-Type: text/plain");
remember: add these lines immediately starting session
We have to allow CORS, placing Access-Control-Allow-Origin:* in header of request may not work. Install a google extension which enables a CORS request.
Make sure the credentials you provide in the request are valid.
if you are passing request to the virtual homestead server, make sure the machine has been provisioned. If you are using vagrant try vagrant up --provision this will make the localhost connect to db of the homestead.
Try changing the content type of the header. header:{ 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8;application/json' }
this point is very important.

Vuejs axios how to pass array with key?

I'm trying to post to my Laravel backend some data as 'offer' array:
That is how it looks in postman and works:
keys: offer[title], offer[description], offer[author_user_id]
now with axios I've tried something like:
offer: {
title: this.input.title,
description: this.input.description,
author_user_id: id,
}
tried also with:
[key=>val] and for example offer.title: value, but also failed.
How it should looks like?
EDIT:
this.axios.post('http://api.wip/api/offer/store', {
offer: {
title: this.input.title,
description: this.input.description,
author_user_id: id,
},
category: 2
}, {
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'application/json'
}
})
.then(function () {
})
.catch(function () {
});
In my console I can see it's sent as:
{"offer":{"title":"asd","description":"asd","author_user_id":"2"},"category":2}:
I recive 500 error from server with response from Laravel that it expects data to be array.
"message": "Argument 1 passed to Illuminate\\Database\\Eloquent\\Builder::create() must be of the type array, null given, called in D:\\wamp64\\www\\apitest\\vendor\\laravel\\framework\\src\\Illuminate\\Support\\Traits\\ForwardsCalls.php on line 23",
As I said it works with postman, but can't make this works from axios
Laravel controller:
public function store(Request $request) {
$offer = Offer::create($request->input('offer'));
$offer->category()->sync($request->input('category'));
$offer->save();
return response()->json($offer);
}
Boussadjra Brahim is right the issue is in the backend But its caused by sending null values from the frontend so we have to take a look at frontend.
first thing is using {} meaning u are creating object , [] is array and laravel create method accept array only
the input is an array itself as u are accessing it keys with (dot) so why not just set offer to the whole array and then separate them in the backend ? like this
axios.post('http://api.wip/api/offer/store', {
offer:this.input,
author_user_id: id,
category: 2
},
in your backend u can access them like :
$title = $request->offer['title'];
one last thing, when u are using create method the keys must be the same name as the column name in database or it will throw error!
hope it helps

Passing in an array of values to an express POST route

I have a mongoose model called Todo that looks like this:
content: [{
contentType: {
type: String,
default: null
},
contentValue: {
type: String,
default: null
}
}]
My express POST route looks like this:
app.post('/todos', authenticate, (req, res) => {
var todo = new Todo({
content: req.body.content
});
res.send(todo)
//I am sending instead of sending the result for testing
});
When I send int test data using Postman the content array is coming back empty "content": []
I have tried several formats of Body in postman including:
{
"content[contentType]": "reminder",
"content[contentValue]": "Will it blend"
}
and
{
"content": {
"contentType": "reminder",
"contentValue": "Will it blend"
}
}
However both come back with empty array.
{
"content": []
}
Do I need to change something on my POST route and\or send in teh data in an alternate format?
content here is a todo sub document, so you should treat it like the following:
app.post('/todos', authenticate, (req, res) => {
var content = req.body.content;
var todo = new Todo();
todo.content.push(content);
todo.save(function(err) {
if (err) throw err;
res.json(todo.toJSON())
//I am sending instead of sending the result for testing
});
});
See: Mongoose SubDocuments

How to access this json object

I'm using express js to send data from mysql. I send it using res.json(theData).
In the client side I get it like this in the console:
{
"data":[
{
"PlazaID":1,
"PlazaName":"fff",
"PlazaAddress":"fff",
"PlazaContactNo":"45645",
"PlazaLanes":"34",
"PlazaStatus":"y",
"ClientID":1
},
{
"PlazaID":2,
"PlazaName":"plaza2",
"PlazaAddress":"p2",
"PlazaContactNo":"000",
"PlazaLanes":"2",
"PlazaStatus":"a",
"ClientID":2
}
],
"status":200,
"config":{
"method":"GET",
"transformRequest":[
null
],
"transformResponse":[
null
],
"url":"/getTollPlaza",
"headers":{
"Accept":"application/json, text/plain, */*"
}
},
"statusText":"OK"
}
I store these values in an array to populate a table using angularjs' ng-repeat like this:
for(i=0;i<response.data.length;i++){
tableArray.push({
plazaid:response.data[i].plazaid,
plazaname:response.data[i].plazaname,
plazaaddress:response.data[i].plazaaddress,
plazacontactnumber:response.data[i].plazacontactnumber,
plazalane:response.data[i].plazalane,
plazastatus:response.data[i].plazastatus,
clientid:response.data[i].clientid
});
}
When I console.log the array the values are undefined.
0: Object
clientid:undefined
plazaaddress:undefined
plazacontactnumber:undefined
plazaid:undefined
plazalane:undefined
plazaname:undefined
plazastatus:undefined
Try this. Please note that variable name are case sensitive.
for(i=0;i<response.data.length;i++){
tableArray.push({
plazaid:response.data[i].PlazaID,
plazaname:response.data[i].PlazaName,
plazaaddress:response.data[i].PlazaAddress,
plazacontactnumber:response.data[i].PlazaContactNo,
plazalane:response.data[i].PlazaLanes,
plazastatus:response.data[i].PlazaStatus,
clientid:response.data[i].ClientID
});
}

Resources