I am trying to send parameters to a web API using axios in nodejs. This is the code snippet I am trying to use:
const app = require('axios');
app.get("https://api.somedomain.com/v1/", {
headers: {
Param1: 'value1',
Param2: 'value2',
Param3: 'value3'
}
})
.then((res) => {
console.log("Executing 'then' block"); // never executes
})
.catch((err) => {
if (err.response) {
console.log(`response.status: ${err.response.status}`);
} else if(err.request) {
console.log(`request.status: ${err.request.status}`);
}
})
When I execute the above I always get a response code 400 from the catch block.
So my question is this:
Can I display the string which is sent to the web API? Something that would look like this output:
https://api.somedomain.com/v1/?Param1=value1&Param2=value2&Param3=value3
Sorry if this seems naive but I have been able to make one get to retrieve a URL I will use to send the second get. The first get works and I have the URL. The second one always gives me the 400 response. (Or perhaps, is it because I have executed one get request on the app object and I have failed to clean up the app object to prepare for the next get request?)
Thanks in advance for your reply.
Peter
Change from headers to params in axios config:
const app = require('axios');
app.get("https://api.somedomain.com/v1/", {
params: { // HERE IS THE CHANGE!
Param1: 'value1',
Param2: 'value2',
Param3: 'value3'
}
})
.then((res) => {
console.log("Executing 'then' block"); // never executes
})
.catch((err) => {
if (err.response) {
console.log(`response.status: ${err.response.status}`);
} else if(err.request) {
console.log(`request.status: ${err.request.status}`);
}
})
Related
This is a course quiz and this is the most basic information I need in order to create a React app. But while the endpoint URL is correct, the page "/products" returns a "400" error when I try to request the product list. The instructions I'm given are:
Obtain a list of products with
Route: /products
Body: Array
method: POST
{
"product-codes": [
"98798729",
"84876871",
"29879879",
]
}
My index.js
...
app.post(`/products`, async (req, res) => {
try {
const response = await axios.post(`${apiURL}/products`);
// console.log(response.data);
res.status(200).json(response.data);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
in Postman
I use http://localhost:4000/products
and pass a Body / Raw /JSON:
{
"product-codes": [
"98798729",
"84876871",
"29879879",
]
}
But I can't get in! I am not seeing something obvious because this is the entry point to a very long and complex quiz. Thanks
What I see from the code is a recursive long call.
app.post(`/products`, async (req, res) => {
try {
const response = await axios.post(`${apiURL}/products`); // calling the same end point
// console.log(response.data);
res.status(200).json(response.data);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
You should do something like this:
app.post(`/products`, async (req, res) => {
// do your logic
// when you pass body from postman on this endpoint
// you will receive the body here and save it to DB
// or do the manipulation and then send back the response
res.status(200).json(req.body.data);
});
I highly recommend you to first follow through some tutorials to understand how API works and how to create simple API using Node.js.
var unirest = require("unirest");
var req = unirest("GET", "https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data");
req.query({
"ingr": "1 large apple"
});
req.headers({
"x-rapidapi-host": "HOST",
"x-rapidapi-key": "KEY",
"useQueryString": true
});
req.end(function (res) {
if (res.error) throw new Error(res.error);
console.log(res.body);
});
Im trying to make an API call with that doc and parameters in order to get a list of ingredients based on a search parameter.
This is my service:
async getAllNutrients(ingr: string) {
console.log(ingr);
const headersRequest = {
'x-rapidapi-host': 'edamam-edamam-nutrition-analysis.p.rapidapi.com',
'x-rapidapi-key': '5664b75c9fmsh66ac8e054422eb9p1600b8jsn878d097e8d2a',
useQueryString: true,
};
const result = await this.httpService.get(
`https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data` +
ingr,
{ headers: headersRequest },
);
console.log(result);
return result;
}
And this is my controller
#Get('/list?:ingr')
getMacros(#Query('ingr') ingr) {
return this.macroService.getAllNutrients(ingr);
}
I tried to change QUery and Param but none are working.
On postman i make an API call like this:
"localhost:3000/macros/list?ingr="1 large apple"
And my 2 console.log returns:
"1 large apple"
Observable { _isScalar: false, _subscribe: [Function] }
[Nest] 7460 - 2020-09-21 16:00:55 [ExceptionsHandler] Request failed with status code 404 +441782ms
Error: Request failed with status code 404
I tried to use pipe like this example:
getQuote(id){
return this.http.get('http://quotesondesign.com/wp-json/posts/' + id)
.pipe(
map(response => response.data)
);
}
But the result was the same. Any help?
Looks like your issue is in your controllers route. Changing #Get('/list?:ingr') to #Get('/list') should resolve this. I believe passing ?:ingr in the path is setting a param with key ingr.
Queries do not need to be added to the route. They are accessed using the #Query decorator.
Look at this for more info.
In your service function
const result = await this.httpService.get(
`https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data` +
ingr,
{ headers: headersRequest },
);
with ingr is 1 large apple then the API URL will become "https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data1 large apple".
I think this is an incorrect API URL, and you don’t want to call the API like that.
Change it to
`https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data?ingr=${ingr}`,
I am trying to send a POST request using axios to the backend but it is throwing a 404 for the path and i dont know why
Here is the react/redux code calling the axios request
export const addGoal = (newGoal: Goal) => {
return (dispatch: any) => {
authMiddleWare(history)
const newValues = newGoal
const authToken = localStorage.getItem('AuthToken')
axios.defaults.headers.common = { Authorization: `${authToken}` }
axios
.post('/goal', newValues)
.then((response) => {
console.log('success', response.data)
dispatch({
type: ADD_GOAL,
payload: response.data,
})
})
.catch((err) => {
console.error('\nCould not submit goal\n', err.response)
})
}
}
This is the nodejs path i have in my main backend file for calling the paths
app.post("/goal", auth, postOneGoal);
This is the backend function for the node path
// ADDS A SINGLE WORKOUT
exports.postOneGoal = (request, response) => {
if (request.body.id.trim() === "" || request.body.text.trim() === "") {
return response.status(400).json({ body: "Must not be empty" });
}
const newGoalItem = {
username: request.user.username,
id: request.body.id,
text: request.body.text
};
db.collection("goals")
.add(newGoalItem)
.then((doc) => {
const responseNewGoalItem = newGoalItem;
responseNewGoalItem.id = doc.id;
doc.update(responseNewGoalItem);
return response.json(responseNewGoalItem);
})
.catch((err) => {
response.status(500).json({ error: "Couldn't add the goal" });
console.error(err);
});
};
I am using a firebase url proxy in my package.json as well.
Let me know if any more info is needed
Posting this as Community Wiki, based in the comments.
Considering the fact that you are using Cloud Functions, you will need to redeploy the functions everytime you update your code. You can check more details on deploying your functions in the official documentation accessible here. There you will have the options regarding how and where you can deploy your functions for better testing.
I have an angular project back end with node.js, how can I call and get httpErrorResponse status or headers to display in my components page when my server is down or not responding.
here is my component function code:
UpdateData(){
this.newServices.updateNews(result, result.id).subscribe(
(res)=>{
console.log(res)
}),
(error)=>{
console.log(error)
}
}
my service.ts function:
updateNews(data, id) {
try {
return this.http.post(this.baseurl + "/news/update/" + id, data)
} catch (err) {
this.handleError(err);
}
}
how can I check in my component the http responses so that I can display messages on the browser
Generally its not advisable to show the error message to the user that returned from server. For example the error may be: Cant reach the xx.xx.xx due to CORS policy. So if u show this the user cant understand whats happening. So its advisable to use a toaster Service to show error to user.
https://www.npmjs.com/package/ngx-toastr
getPlayersList() {
this.playerService.getPlayersList().subscribe((res: any) => {
this.playersData = res.data;
}, err => {
this.toasterService.showFailure('Sorry something went wrong');
})
}
In some scenarios if u want to show the error thats coming from api like 500 response u can do in this way
getPlayersList() {
this.playerService.getPlayersList().subscribe((res: any) => {
this.playersData = res.data;
}, err => {
this.toasterService.showFailure(err.err.message);
})
}
Try this:
In your service:
updateNews(data, id) {
return this.http.post(this.baseurl + "/news/update/" + id, data)
}
In your function:
this.newServices.updateNews(result, result.id).subscribe(
(res)=>{
console.log(res)
}),
(error)=>{
console.log(error)
}
I have some promise
getSomeInfo(data) {
return new Promise((resolve, reject) => {
/* ...some code... */
someObject.getData((err, info) => {
if (info) {
resolve(info)
}
else {
reject("Error")
}
})
})
}
I use this promise and want to send response to client from Controller (AdonisJS):
async create ({ request, response }) {
this.getSomeInfo(data).then(info => {
console.log(info) // It's work, i get the data from promise
response.status(201).json({ // but this is not work
code: 201,
message: "Data received!",
data: info
})
})
}
Why response is not work?
Simply do this.
async create ({ request, response }) {
const info = await this.getSomeInfo(data)
console.log(info)
response.status(201).json({
code: 201,
message: "Data received!",
data: info
})
}
When marking a function as async the function must return a Promise, this can be done explicitly.
async create({ request, response }) {
return this.getSomeInfo(data).then(info => {
console.log(info) // It's work, i get the data from promise
response.status(201).json({ // but this is not work
code: 201,
message: "Data received!",
data: info
})
})
}
Or implicitly using the await keyword.
async create({ request, response }) {
const info = await this.getSomeInfo(data)
console.log(info) // It's work, i get the data from promise
response.status(201).json({ // but this is not work
code: 201,
message: "Data received!",
data: info
})
}
If your console.log(info) inside of create() works and shows the data you want, but the response.status(201).json(...) does not send a response, then I can see the following possibilities:
You've already sent a response to this request (and thus cannot send another one)
The .json() method is having trouble converting info to JSON (perhaps because of circular references) and throwing an exception.
You aren't passing the arguments request and response properly and thus response isn't what it is supposed to be.
You can test for the second case like this:
create ({ request, response }) {
this.getSomeInfo(data).then(info => {
console.log(info) // It's work, i get the data from promise
response.status(201).json({ // but this is not work
code: 201,
message: "Data received!",
data: info
});
}).catch(e => {
console.log("Error in create()", e);
response.sendStatus(500);
});
}
Also, there is no reason for this method to be declared async as you don't show that you're using await or any of the features of an async function.
In the comments, you say that this function is called directly by a router (I assume an Express router). If that's the case, then the function arguments are not declared properly as they come as two separate arguments, not as properties of an object. Change the function declaration to this:
create (request, response) { ... }