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
Related
I am trying to send the contents of a flashcard to a backend route http://127.0.0.1:5000/post onClick and it works when I send the data to webhook.site but when I change it to http://127.0.0.1:5000/post I get the error " question = data['question' TypeError: 'NoneType' object is not subscriptable ". Here is the code for the fetch request:
async function postData() {
try {
let result = await fetch('http://127.0.0.1:5000/post', {
method: 'POST',
mode: 'no-cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
key: `${Date.now()}`,
question: flashcard.question,
answer: flashcard.answer,
options: flashcard.options
})
});
} catch(e) {
console.log(e)
}
}
and here is the code for the backend route in flask:
#app.route('/post', methods=['GET', 'POST'])
def post():
#save data to db
data = request.get_json()
question = data['question']
answer = data['answer']
options = data['options']
key = data['key']
return jsonify({'question' : question, 'answer' : answer, 'options' : options, 'key' : key})
if __name__ == "__main__":
app.run(debug=True)
I get that the error is stating that "data" has no value which I assume means it's not recieving the JSON objects that I'm posting. It's weird because it works perfectly when I use a webhook.site url. can anyone help? thanks for your time!
Seems like your content is not a valid json request. If that is the case then content will be equal to None(not subscriptable).
Try to debug how data looks in flask and based on that you will know if its valid json.
I've been using vanilla Django as a backend to my React frontend. I'm trying to make a POST request using axios that passes a dictionary of 2 values to my django view, and so far on my front end the values are valid, the connection to the django url is made, but the only issue is the actual data being processed in the view. If I try to print the value, it returns as None. Heres what I have so far:
Relevant Code
views.py
def render_data(request):
reddit_url = request.POST.get('reddit_url')
sort = request.POST.get('sort')
print(reddit_url, sort)
users_data, count = run_data(reddit_url, sort)
data = {
'users_data': users_data,
'count': count,
}
return JsonResponse(data)
component.jsx
const APIcall = () => {
axios
.post(
`http://127.0.0.1:8000/reddit_data/`,
{
reddit_url: location.state.link,
sort: location.state.sort,
},
{
headers: {
"Content-Type": "application/json",
"X-CSRFToken": location.state.token,
},
withCredentials: true, //cors requests
}
)
.then((res) => {
console.log("YESSIR");
setLoading(false);
});
};
Expected/actual output
Ideally, the output would print the values from the request, but the actual result is just None, None.
What I tried
I tried using request.POST['reddit_url'] with no different results
Double checking the frontend values to make sure the POST call is going through with the correct values
I'll be honest I havent tried much I really cant understand this one
Turns out, my QueryDict was returning empty in my Django console while trying to print it, and I simply solved it by using var formData = new FormData(); appending my values, then using it as a parameter in my axios post to make a POST request.
So I have never post a data using FormData and multipart/form-data as Content-Type in my React project. But now I'm kinda forced by backend to send it this way since we have some images in payload.
The problem is that the whole data is a JS object and can be parsed to JSON, and nothing more. So how can I convert my JS object into a valid FormData that backend would accept it? Everything works without a problem in Postman, but in the app I always get the same error.
Here is some more detail:
The working Postman sample:
What I expect to be working (but obviously doesn't):
const createProd = () =>
HttpRequest.post('/api/prod', {
body: {
Product: {
title: 'Test Prod',
shop: null,
description: "My new ad's description",
category: { id: '5d8c6aa6fadeaf26b0194667' },
condition: 'USED'
}
});
HttpRequest is a helper function which uses ES6 fetch for requests.
I always get the same error: "Required request part 'Product' is not present" with/without JSON.stringify.
I even tried to create a sample FormData to at least change the error:
cont payload = new FormData();
payload.append('Product', {foo: 'bar'});
But still same error. I also copied the code which is generated by Postman. But still no chance.
I would be thankful if you share your suggestions or workarounds.
Thanks in advance.
const formData = new FormData();
const product = { //your product object };
formData.append('product', JSON.stringify(product));
const config = {
headers: {
'Content-Type': 'multipart/form-data; charset=utf-8; boundary="another cool boundary";'
}
};
axios.post(`/api/ads`, formData, config).then((res) => {
console.log(res);
}).catch(err => {
console.log(err);
});
Maybe you should set header.
Try this one. In my case I used Axios. It worked for me in my project.
Im having what seems to be a very common error when working on the Spotify API adding tracks to a users playlist. In a previous fetch method I have obtained the users playlistId and am now trying to post tracks onto that playlist with that playlistId. I have followed the documentation but am obviously missing something, here is code:
` //userUd, playlistId, currentUserAccessToken, trackURIs are all defined
fetch(`https://api.spotify.com/v1/users/${userId}/playlists/${playlistId}/tracks`, {
headers: {
'Authorization': 'Bearer ' + currentUserAccessToken
},
contentType: 'application/json',
method: 'POST',
body: JSON.stringify({
"uris": `[${trackURIs}]`
})
}).then(success => {
return success;
}).catch(err => {
console.log('here is your error', err);
})`
I did the GET request to authorize user - included scope for creating public playlist, in different code block which is working, here's that:
`let scopes = 'playlist-modify-public';
window.location.replace(https://accounts.spotify.com/authorize?client_id=${clientID}&scope=${scopes}&redirect_uri=${redirectURI}&response_type=token);`
Thanks a ton!
The JSON array needs quotes around each element in it. So each track should be quoted, like so:
{"uris": ["spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "spotify:track:1301WleyT98MSxVHPZCA6M"]}
I think you're supplying an object names uris with an invalid array.
And, note you can pass the playlist items as query params too (instead of in the body), without using json. https://developer.spotify.com/web-api/add-tracks-to-playlist/
I have a Lambda function that handles reading data from a file(stored inside S3 bucket) as well as inserting data to a Dynamodb table. This Lambda function is exposed as a REST endpoint using API gateway. The function accepts GET request as well as POST request. I'm making GET/POST requests from my REACT project using axios and aws4(for signing) libraries. GET request is to read data from a file stored inside S3 and it works just fine. And POST request is for inserting data into Dynamodb table. However, it doesn't work and AWS returns InvalidSignatureException error as a respond. This is an excerpt of my code :
createAWSSignedRequest(postData) {
let request = {};
if (postData) {
request = {
host: process.env.AWS_HOST,
method: 'POST',
url: process.env.AWS_URL,
path: process.env.AWS_PATH,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
}
} else {
request = {
host: process.env.AWS_HOST,
method: 'GET',
url: process.env.AWS_URL,
path: process.env.AWS_PATH
}
}
let signedRequest = aws4.sign(request, {
secretAccessKey: process.env.AWS_SECRET_KEY,
accessKeyId: process.env.AWS_ACCESS_KEY
});
return signedRequest;
}
This is how GET request is made :
let signedRequest = this.createAWSSignedRequest('GET');
axios(signedRequest)
.then(response => {
})
.catch((error) => {
console.log("error",error);
});
This is how POST request is made :
const data = {
uuid: "916b7d90-0137-11e8-94e6-116965754e23", //just a mock value
date : "22/jan/2018",
user_response: [
{
question:"this is quesiton1",
choice:"user selected A"
},
{
question:"this is quesiton2",
choice: "user selected b"
},
{
question:"this is quesiton3",
choice: "user selected C"
}
]
};
let signedRequest = this.createAWSSignedRequest(data);
axios(signedRequest)
.then(response => {
......
})
.catch((error) => {
console.log("error",error);
});
As you can see, the code for both GET and POST requests are exactly the same (except payload and method type). I'm singing with the same secret access key and access key id for both requests. I'm not sure why one request results in "InvalidSignatureException" when the other doesn't. Can anyone shed a light on this issue for me.
Thanks
After having discussion with AWS4 lib developer, I figured out what I did wrong. AWS4 uses "body" as a payload attribute to compute signature. However, Axios uses "data" attribute as payload. My mistake was only setting either one of them. So when I set just "data" attribute, the payload was present in the request and content-length is computed correctly. However, the signature was incorrect since the payload was not taken into consideration when computing signature. When I set just "body", payload was not present in the request because Axios does not use "body" attribute for payload. The solution is to set both attributes with payload. I hope this helps to anyone who are having the same issue I have.
If you use the AWS Amplify library it has a module called API which should fit your use cases, and it will perform Sigv4 signing for you either with authenticated or unauthenticated roles. The Auth category uses Cognito as the default implementation. For instance:
npm install aws-amplify --save
Then import and configure the lib:
import Amplify, { API } from 'aws-amplify';
Amplify.configure({
Auth: {
identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab',
region: 'XX-XXXX-X'
},
API: {
endpoints: [
{
name: "APIName",
endpoint: "https://invokeURI.amazonaws.com"
}
]
}
});
Then for your API Gateway endpoint calling a Lambda:
let apiName = 'MyApiName';
let path = '/path';
let options = {
headers: {...} // OPTIONAL
}
API.get(apiName, path, options).then(response => {
// Add your code here
});
More info here: https://github.com/aws/aws-amplify