Can't intercept and manipulate data with Axios [duplicate] - javascript

I am using axios in my Express API and I want to transform the payload before sending it off to another API. axios has just the thing for this called transformRequest. This is where I ran into issues though.
The code I have looks like:
const instance = axios.create({
baseURL: 'api-url.com',
transformRequest: [
(data, headers) => {
const encryptedString = encryptPayload(JSON.stringify(data));
data = {
SecretStuff: encryptedString,
};
return data;
},
],
});
// firing off my request using the instance above:
const postData = {
id: 1,
name: 'James',
};
instance.post('/getStuff', postData)
and ultimately, I want to post api-url.com the JSON: {"SecretStuff": "some-base64-string"} - not the postData object shown above.
From the docs, it says: "The last function in the array must return a string or an instance of Buffer, ArrayBuffer, FormData or Stream" - but of course here I am returning an object, data. Oddly enough in the axios docs it shows them returning data from transformRequest, but in their case that must be the correct data type.
How do I actually transform a payload with axios?

axios.create({
transformRequest: [(data, headers) => {
// modify data here
return data;
}, ...axios.defaults.transformRequest]
});
have to append the original axios.defaults.transformRequest to the transformRequest option here..

Wouldn't you want to JSON.stringify() your transformed post data? Like below:
const instance = axios.create({
baseURL: 'api-url.com',
transformRequest: [
(data, headers) => {
const encryptedString = encryptPayload(JSON.stringify(data));
data = {
SecretStuff: encryptedString,
};
return JSON.stringify(data);
},
],
});

To amend the values instead of override the output in the request I would do this:
const instance = axios.create({
baseURL: 'api-url.com',
transformRequest: [
(data, headers) => {
data.append('myKey','myValue');
return data;
},
]
});

Here's what worked for me in TypeScript, inspired by the concat solution from Phil here: https://stackoverflow.com/a/70949237/2339352
The goal here was to use the humps library to convert to/from a snake case Python API:
this.axios = axios.create({
transformResponse: (data: any) => {
return humps.camelizeKeys(JSON.parse(data))
},
transformRequest: [(data: any) => {
return humps.decamelizeKeys(data);
}].concat(axios.defaults.transformRequest ? axios.defaults.transformRequest : [])
});

Related

axios GET request with form data in React JS

I want to implement the following cURL request (which is working) in react js using axios:
curl -k --request GET "BASE_URL_SERVER/sendText" --form "user_id="uidxxxx"" --form "sign_id="
I always get the same error: field sign_id not found, but technically I'm sending it, so I'm kind of desesperate.
var data = new FormData();
data.append('user_id', 'uidxxxx');
data.append('sign_id', '9');
const api = axios.create({
baseURL: BASE_URL_SERVER,
data: data,
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`
},
timeout: 10000,
})
api.get('/sendText')
.then(response => console.log(JSON.stringify(response.data)))
.catch(error => { console.log(error) })
I've also tried adding '...getHeaders()' to the headers section but React says it is not a function; I've read in other posts that it has something to do with the browser
thanks in advance
ps: it is a pretty similar problem to this one, but none of the solutions worked for me
[UPDATE]
I ended up implementing it with POST, which is better for posting Form Data; no headers are needed, the browser automatically adds them:
var data = new FormData();
data.append('user_id', user_id);
data.append('sign_id', sign_id);
const api = axios.create({
baseURL: BASE_URL_SERVER,
timeout: TIMEOUT_SERVER,
})
api.post('/sendText', data)
.then(response => console.log(JSON.stringify(response.data)))
.catch(error => { console.log(error) })
You have a mistake, you try to send data via axios for POST and method is GET...
So that, You need to Change Method to be POST to can Post form data or you need to change it to url param or url path base on your api to be WORK as a GET...
Base on your curl, your case is you need a GET:
// Make a request for a user with a given ID
axios.get('/sendText?ID=12345')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
// Optionally the request above could also be done as
axios.get('/user', {
params: {
sendText: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
Also, you can save all config in instance and share it for all nested of write it again and again..
for example:
// Common Axios Instance Config
const axiosConfig = {
baseURL: process.env.REACT_APP_API_ENDPOINT,
};
// Create Default Axios Instace
const instance = axios.create(axiosConfig);
I think base on your example this will work, but not sure sine I'm not test it..:
var data = new FormData();
data.append('user_id', 'uidxxxx');
data.append('sign_id', '9');
const api = axios.create({
baseURL: 'https://193.146.38.4:56076',
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`
},
timeout: 10000,
})
api.get('/sendText', {
user_id: 111,
sign_id: 2222
)
.then(response => console.log(JSON.stringify(response.data)))
.catch(error => { console.log(error) })
For more details view this url

MERN Stack, axios post current state to DB error 400 bad request [duplicate]

I am trying to create a postHTTP request with some form parameters that are to be set. I am using the axios with node server. I already have a java code implementation of constructing a url as given below:
JAVA CODE:
HttpPost post = new HttpPost(UriBuilder.fromUri (getProperty("authServerUrl"))
.path(TOKEN_ACCESS_PATH).build(getProperty("realm")));
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
formParams.add(new NameValuePair("username",getProperty ("username")));
formParams.add(new NameValuePair("password",getProperty ("password")));
formParams.add(new NameValuePair("client_id, "user-client"));
I am trying to do the same thing in axios.
AXIOS IMPLEMENTATION:
axios.post(authServerUrl +token_access_path,
{
username: 'abcd', //gave the values directly for testing
password: '1235!',
client_id: 'user-client'
}).then(function(response) {
console.log(response); //no output rendered
}
Is the approach to set these form params on the post request correct?
You have to do the following:
var querystring = require('querystring');
//...
axios.post(authServerUrl + token_access_path,
querystring.stringify({
username: 'abcd', //gave the values directly for testing
password: '1235!',
client_id: 'user-client'
}), {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
}).then(function(response) {
console.log(response);
});
If your target runtime supports it, Axios is able to accept a URLSearchParams instance which will also set the appropriate Content-type header to application/x-www-form-urlencoded
axios.post(authServerUrl + token_access_path, new URLSearchParams({
username: 'abcd', //gave the values directly for testing
password: '1235!',
client_id: 'user-client'
}))
The same goes for the fetch API
fetch(url, {
method: "POST",
body: new URLSearchParams({
your: "object",
props: "go here"
})
})
Why pull in another library or module to do something so simple with pure vanilla JavaScript? It's really one line of JS to produce the desired data to submit in your POST request.
// es6 example
const params = {
format: 'json',
option: 'value'
};
const data = Object.keys(params)
.map((key) => `${key}=${encodeURIComponent(params[key])}`)
.join('&');
console.log(data);
// => format=json&option=value
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data,
url: 'https://whatever.com/api',
};
const response = await axios(options); // wrap in async function
console.log(response);
I agree with jhickok, no need to pull in an additional library however their code will not produce a correct result due to the usage of Object.entries, you would expect to see the following:
"format,json=0&option,value=1"
Instead Object.keys should be used.
const obj = {
format: 'json',
option: 'value'
};
const data = Object.keys(obj)
.map((key, index) => `${key}=${encodeURIComponent(obj[key])}`)
.join('&');
console.log(data); // format=json&option=value
Then of course...
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data,
url: 'https://whatever.com/api',
};
const response = await axios(options);
const body = new URLSearchParams();
body.append('param1', 'param1_value');
...
...
axios.post(url,body)

How to pass a query param in post call in Reactjs

I am new to reactjs.I am doing a post call but not sure, how to pass a boolean value in url as a query param in reactjs. For eg: http://www.abx.com?example=true. How do I pass this example in post api call.
Endpoint: API_SAMPLE: "/sample",
post call:
postCall() {
const config = {
headers: {
accept: "application/json",
"Content-Type": "application/json",
},
};
const data = {
product: {
body
},
};
return http
.post(this.API.API_SAMPLE, data, config)
.then((response) => {
return response.data;
})
.catch((error) => {
throw error;
});
}
i want to add a boolean value in my query param, how will i do that
You can use template literals to pass the variable to your URL.
const example = true;
const url = `http://abx.com/sample?example=${example}`
or use it this way:
return http.post(`${this.API.API_SAMPLE}?example=${example}`, data, config) {...}
wether you are using POST or GET you will have to modify the URL.
You can do this "dynamically" or you can use something like URLSearchParams:
https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
var URL = "http://example.com/search";
var searchParams = new URLSearchParams(URL);
searchParams.append("example", "true");
searchParams.toString() // "http://example.com/search?example=true";
Just make sure you support the correct browsers:
https://caniuse.com/#search=urlsearchparams

Error while sending a request to fluxpoint api

it's me again... Sorry for asking so many times a day, but I'm really an idiot.
So basically I'm trying to send a request to the fluxpoint api by using this code:
async welcome(username, avatarurl, background, membercount, icon, backgroundname, filename){
let req = {}
req.username = username;
req.avatar = avatarurl;
if (background == null) {req.background = "#aaaaaa"} else {req.background = background}
if (membercount) req.members = "Member #"+membercount
if (icon) req.icon = icon
if (backgroundname) req.banner = backgroundname
console.log(req)
let usedClient = axios.create({
baseURL: apiUrls[0],
timeout: 5000,
headers: {
'Authorization': this.token,
'Content-Length': 0,
'Content-Type': 'application/json'
},
data: JSON.parse(req),
responseType: 'arraybuffer'
})
console.log(usedClient)
console.log(apiUrls[0]+api1endpoints[1])
let res = await usedClient.get(api1endpoints[1])
return res
}
Here is the code I'm using for testing it:
const fluxpoint = require('./index')
const Client = new fluxpoint.Client("my fluxpoint token")
async function tt(){
let t = await Client.welcome("Koro~ (Baka)#7963", "https://cdn.discordapp.com/avatars/304541381798658048/36806f6ae648b9ebc8303443b0be101c.png", "#FFFFFF", 1, "neko", "space")
console.log(t)
}
tt()
And, here is the error the fluxpoint api sends me:
Failed to parse json, The input does not contain any JSON tokens. Excepted the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
I tried everything, but JSON.parse(my data) sends me Unexcepted token o in JSON at position 1
I'm being desesperate and I hope somebody can help me!
It seems you are parsing the raw json.It throws an error
JSON.parse takes string as parameter.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
And from official doc you cannot use data in get request.
https://github.com/axios/axios#request-config
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', and 'PATCH'
// When no `transformRequest` is set, must be of one of the following types:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - Browser only: FormData, File, Blob
// - Node only: Stream, Buffer
data: {
firstName: 'Fred'
}
So try passing the data
let res = await usedClient.get(api1endpoints[1],{
params: {
data: res
}
})
I've tested the endpoint it works only if responseType is 'text' or 'stream'

Check Axios request url before sending

API requests are failing because the URL generated by Axios is incorrect due to my config. I know what the request url is suppose to look like, so I want to see the request url Axios generates.
I can point Axios to my local server and see the requests there, but I want to debug this on the client. I want to play with the config, and see how the requests change. Is there a way to output the request url from Axios before or after sending?
// param format
{ address: 'Vancouver', key: GOOGLE_API_KEY }
// Geocode sample
https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY
_request = async (...args) => {
const { outputFormat, params } = args
const instance = axios.create({
baseURL: `https://maps.googleapis.com`,
})
const response = await instance.get('/maps/api/geocode/${outputFormat}?', {
params,
})
// I want to see the url generated by Axios so I can debug the issue
console.log(response)
}
I am within the Expo, React Native environment.
Working example using fetch:
const url = `https://maps.googleapis.com/maps/api/geocode/json?address=vancouver&key=${GOOGLE_API_KEY}`
fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(data)
})
.catch(function(error) {
console.log(error)
})
Solution used:
_request = async (obj) => {
const { outputFormat, params } = obj
const instance = axios.create({
baseURL: `https://maps.googleapis.com`,
})
instance.interceptors.request.use(function (config) {
console.log(config)
return config
}, function (error) {
return Promise.reject(error)
})
const response = await instance.get(`/maps/api/geocode/${outputFormat}`, {
params,
})
}
You can turn on debug mode and look at the network tab as mentioned in the other answer, or you can intercept axios and console.log or do whatever you want with the request before it's sent:
axios.interceptors.request.use(function (config) {
// Do something before request is sent
console.log(config)
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
You can just use axios#getUri([config]) (source) to perform the same logic as the request. It merges the configurations (e.g. the given config and the instance configuration), merges the url with the baseURL, and appends any params using the paramSerializer.

Categories

Resources