Passing through an array with axios - reactjs

I am having an issue passing through an array through axios post call. The issue is that on the api endpoint the data received is null, when I try posting using postman it works fine so the endpoint is working. Example of the array
I need to pass the data in this format:
{
"UpdateItemList": [
{
"Text": 1,
"Value": "5"
},
{
"Text": 1,
"Value": "5"
}
]
}
Code:
export function createLogEntry(postData) {
let payload = {
UpdateItemList: postData
};
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry', {
data: payload
});
return {
type: CREATE_LOG,
payload: request
}
}
Is there any issue with the way I am passing through the data with my current code?

Try with
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry',payload);
This worked for me!

The issue is that you are confusing two ways axios can be used. Currently you are actually posting your data nested in an object within and the key data:
{
data: {
UpdateItemList: postData
}
}
If you are using the axios.post function, you should just pass your object with the data to post as the second object like this:
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry', payload);
If you are using the config object method, you should just pass one single object with url, method and data as keys.
// Send a POST request
axios({
method: 'post',
url: 'https://localhost:44312/api/Audit/AddLogEntry',
data: payload
});
This behaviour is explained in the axios Readme here: https://github.com/axios/axios#axios-api

Related

Django views not returning a value from a multiple parameter request?

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.

How to post data when you have javascript object using multipart/form-data content-type

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.

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

InvalidSignatureException from POST request

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

How to add additional request body values to Apollo GraphQL request?

I'm using Apollo with the Scaphold.io service and for writing blobs to that service I need to be able to add additional options to the request body.
The full Scaphold example can be found here: https://scaphold.io/docs/#uploading-files
But it does something like this:
form.append("variables", JSON.stringify({
"input": {
"name": "Mark Zuck Profile Picture",
"userId": "VXNlcjoxMA==",
"blobFieldName": "myBlobField"
}
}));
// The file's key matches the value of the field `blobFieldName` in the variables
form.append("myBlobField", fs.createReadStream('./mark-zuckerberg.jpg'));
fetch("https://us-west-2.api.scaphold.io/graphql/scaphold-graphql", {
method: 'POST',
body: form
}).then(function(res) {
return res.text();
}).then(function(body) {
console.log(body);
});
Where it adds a blobField to the request body.
Based on this, I need to pass into the variables a blobFieldName property, and then add to the request body the value passed to that property with the blob. However, using Apollo I can't add to the request body. I tried the following, but it's absent from the request body when I check in the network inspector:
export const withCreateCoverPhoto = graphql(CreateCoverPhoto, {
props: ({mutate}) => ({
createCoverPhoto: (name, file) => mutate({
variables: {
input: {
blobFieldName: name,
},
},
[name]: file
}),
}),
});
Please advise.
Thanks for the question. Currently the best way to upload files is by [appending it to FormData and sending it up to the server using fetch] (https://medium.com/#danielbuechele/file-uploads-with-graphql-and-apollo-5502bbf3941e). Basically, you won't be able to have caching here for the file itself, but this is the best way to handle uploading files on Scaphold using a multipart request.

Resources