Getting "EHOSTUNREACH" when trying to connect to API using Axios + Express.js - node.js

I started playing around with the Philips Hue Bridge API by sending it requests using Postman. I was able to authenticate myself, create a user and even successfully turn lights on or off.
Conclusion: I am able to reach the API.
Next I made a mini test javascript file to do the exact same using Node.js and axios#0.21.4. When I try the following code everything works and I receive the expected JSON responses:
const axios = require('axios')
axios({
method: 'GET',
url: 'http://philips-hue.local/api/BYLCIlxABzz2eDHAxx70T'
})
.then(({data}) => {
console.log('------> AXIOS RES: ', data)
})
.catch((err) => {
console.log('------> AXIOS ERR: ', err)
})
Conclusion: Axios is able to communicate with the API.
Next I wanted to build this into an Express.js endpoint. However when I try to use the same code inside of express#4.17.1 I get an error:
router.route('/getlights').get((req, res) => {
axios({
method: 'GET',
url: 'http://philips-hue.local/api/BYLCIlxABzz2eDHAxx70T/lights'
})
.then(({data}) => {
console.log('------> AXIOS RES: ', data)
res.json({
state: 'SUCCESS',
data
})
})
.catch((err) => {
console.log('------> AXIOS ERR: ', err)
res.json({
state: 'ERROR',
err
})
})
})
Response:
{
"state": "ERROR",
"err": {
"message": "connect EHOSTUNREACH 192.168.0.107:80",
"name": "Error",
"stack": "Error: connect EHOSTUNREACH 192.168.0.107:80\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1161:16)",
"config": {
"url": "http://philips-hue.local/api/BYLCIlxABzz2eDHAxx70T/lights",
"method": "get",
"headers": {
"Accept": "application/json, text/plain, */*",
"User-Agent": "axios/0.21.1"
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1
},
"code": "EHOSTUNREACH"
}
}
I started troubleshooting the problem by first trying to changing the URL to a random online place holder like http://jsonplaceholder.typicode.com/posts/1 just to see if I could establish any connection at all. This actually worked right away.
This is where I got really confused. Why am I able to successfully communicate with the bridge using Postman or Axios in a javascript file, but NOT able to connect with it when the same Axios code is used by express. The problems seems to occur only when using both axios and express to connect to the bridge API.
I have already tried retesting this with node-fetch and 3 other versions of Axios. All tests failed the exact same way. The code by itself can always connect to the API but once the code is being called by express it causes the EHOSTUNREACH error.
I ran out of ideas on how to further google this issue since I am not sure what exactly is causing the problem (express and/or axios and/or bridge). Any trouble shooting ideas or google keywords are also very welcome. :)

I had the same error, for some reason the ip address of my hue bridge had changed so I went into the hue app on my smartphone and copied the new ip address. IDK if this is helpfull, im pretty new here.

I had the same error since yesterday, and couldn't find solution. What actually caused mine was, there was a bearer token on the 3rd party api I called and i also pass it through the header as well.
So it was removed and pass the token through header and it works fine.
UPDATE: error keeps showing up if send another request.
The solution i found was to use request.
const request = require('request');
const headers = {
'Content-Type': 'application/json',
'token': `${token}`
};
const data = {
username : 'username'
}
let options = {
method: 'POST',
url: 'url',
port: 443,
headers: headers,
body: data,
json: true
};
request(options, async (error, res, body) => {
if (error) {
console.log({error});
return response.status(500).json({
status: false,
message: "Error occured"
});
} else {
console.log({body});
return response.status(201).json({
message: "success"
});
}
});

Related

How to code a javascript JSON RPC from scratch, problem with the response

I'm trying to code a json rpc from scratch. I tried using a fetch, but what the server returns is not the information I want. I believe I need to stay connected waiting for a return from the server. My purpose is to make a request to ganache and get a response. From the ganache log I see that he received the request, but I don't know how to get his return. My initial code was as follows.
const nodeFetch = require('node-fetch')
async function run() {
const retorno = await nodeFetch('HTTP://127.0.0.1:7545', {
method: 'POST',
body: JSON.stringify({
"jsonrpc": "2.0",
"method": "eth_accounts",
"params": [],
"id": 1
}),
headers: {
'Content-Type':'application/json'
}
})
console.log(retorno)}
run();
The answer I get is
Thx

API call from https node application never reaches the destination

I have a node.js application served over https. I would like to call an API from that application. The API is also served over https and it has been generated using the express-generator.
Unfortunately the call never works. There is no error message. The call never reaches the API.
Strangely enough if I try to call another public API (e.g. https://api.publicapis.org/entries') that is working perfectly.
Here is my call:
const requestBody = {
'querystring': searchQuery,
};
const options = {
rejectUnauthorized: false,
keepAlive: false, // switch to true if you're making a lot of calls from this client
};
return new Promise(function (resolve, reject) {
const sslConfiguredAgent = new https.Agent(options);
const requestOptions = {
method: 'POST',
body: JSON.stringify(requestBody),
agent: sslConfiguredAgent,
redirect: 'follow',
};
fetch('https://192.168.112.34:3003/search', requestOptions)
.then(response => response.text())
.then(result => resolve(result))
.catch(error => console.log('error', error));
});
};
And here is the API which I would like to call:
router.post('/', cors(), async function(req, res, next) {
req.body;
queryString = req.body.querystring;
let data = JSON.stringify({
"query": {
"match": {
"phonetic": {
"query": queryString,
"fuzziness": "AUTO",
"operator": "and"
}
}
}
});
const { body } = await client.search({
index: 'phoneticindex',
body: data
});
res.send(body.hits.hits)
});
What is wrong with my API and/or the way I am trying to communicate with it?
UPDATE: I receive the following error in the fetch catch block: 'TypeError: Failed to fetch'
When I create a request in Postman I receive the expected response.
UPDATE 2: This is most probably an SSL related issue. The webapp is expecting an API with a valid certificate. Obviously my API can only have a self signed cert which is not enough here. How can I generate a valid cert for an API which is running on the local network and not publicly available?
UPDATE 3: I managed to make it work by changing the fetch parameters like this:
fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
mode: 'cors',
body: raw,
agent: httpsAgent,
redirect: 'follow',
})
and on the API side I added the following headers:
'Content-Type': 'application/json',
'Access-Control-Allow-Origin' : 'https://localhost:2200',
'Access-Control-Allow-Methods' : 'POST',
'Access-Control-Allow-Headers' : 'Content-Type, Authorization'
I also added app.use(cors()) and regenerated the self-signed certificates.

Basic Auth is not working with Axios post Nodejs

I am trying to send a request using axios post with basic authorization. It is working fine with postman but not working when I try to send via code.
axios.post(`my-url`, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic **KEY_HERE**',
},
data: {
'id': 'event_order',
'date': '2021-09-09'
}
}).then(async (response) => {
console.log(response.data)
})
It is returning 401 Unauthorized. But, it works as excepted when I call it via Postman:
Postman Setup Image
Did you add your domain to whitelist in your cors module? If not:
app.use(cors({ origin: "PROTOCOL://DOMAIN:PORT", credentials: true }));
edit: Ok, sorry, I was confused and thought you were sending a frontend axios post request to your own NodeJS server. If possible, could you be more precise. But try passing in your headers/auth as the third argument-- since you're passing in everything in the second argument, the API is not parsing out your headers since its part of the data parameter.
const data = {
'id': 'event_order',
'date': '2021-09-09'
}
axios.post(`my-url`, data, {
headers: {'Content-Type': 'application/json'},
auth: {
username: "YOUR_USERNAME",
password: "YOUR_PASS"
}
})
.then(async (response) => {
console.log(response.data)
})
Also try and post the network errors, if you can.

Axios Post Request in NodeJS

I have an API call in POSTMAN, which I am trying to replicate in nodeJS project using Axios, but the result is not the same that of a POSTMAN.
The call looks like this in POSTMAN:
Inside the body element I have: models and values properties and Authorization is of type Bearer .
I get a response result as an array.
Now, I try to do the same using axios, but I get error:
Code
axios.defaults.baseURL = 'http://XXXXXXXXXXXXXXX:8069/api';
axios({
method: 'POST',
url: '/create/res.users',
data: {
models: 'res.users',
values: "{ 'login': 'john#gmail.com', 'name':'john', 'email':'john#gmail.com', 'password': '123123123' }"
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + accessToken
},
})
.then(function (response) {
console.log("Register", response);
res.status(200).send({
message: response.data
});
})
.catch(function (error) {
console.log("Error", error.response.data);
res.status(error.response.status).send({
message: error.response.data
});
});
Error
{
"message": {
"name": "odoo.exceptions.RedirectWarning",
"message": "You cannot create a new user from here.\n To create new user please go to configuration panel.\n74\nGo to the configuration panel",
"arguments": [
"You cannot create a new user from here.\n To create new user please go to configuration panel.",
74,
"Go to the configuration panel"
],
"exception_type": "error",
"code": 500,
"description": "Restful API Error"
}
}
By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded format instead, This document may help you:
https://github.com/axios/axios#using-applicationx-www-form-urlencoded-format

Getting 400 Bad Request When POSTing to Get Transaction Token

I'm trying to integrate our website with Converge API with Hosted Payments Page. Here is the link to their documentation https://developer.elavon.com/#/api/eb6e9106-0172-4305-bc5a-b3ebe832f823.rcosoomi/versions/5180a9f2-741b-439c-bced-5c84a822f39b.rcosoomi/documents?converge-integration-guide/book/integration_methods/../../book/integration_methods/hosted_payments.html
I'm having troubles getting past the first step which is requesting a transaction token from their API endpoint. I'm sending a POST request from my server using axios with the correct parameters and URL, but when I try and POST i get 400 Bad Request. When I make the same request in POSTMAN I get a 200 response with the transaction token. I talked to their developers and they said that everything I was doing was correct and that nothing seemed odd within my code, so even they were stumped as to why I couldn't make a POST request to their endpoint. Obviously there is something within my code that their API is not liking, or else I wouldn't be here trying to find answers for this.
Here is how I'm making the POST request:
app.get('/converge_token_req', (request, response) => {
let params = {
ssl_merchant_id: '*****',
ssl_user_id: '*****',
ssl_pin: '*****',
ssl_transaction_type: 'ccsale',
ssl_amount: '1.00'
}
axios.post('https://api.demo.convergepay.com/hosted-payments/transaction_token', params, {
headers: { 'Content_Type' : 'application/x-www-form-urlencoded' }
}).then((res) => {
response.send(res.data)
}).catch((error) => {
console.log('there was an error getting transaction token')
response.send(error.message)
})
})
Here are the Request Headers:
I'm honestly out of ideas to try. The developers say that everything looks just fine yet I'm unable to make a successful request to their API. If anyone has any thoughts on this that would be great. Thanks!
This code below worked for me:
app.get('/converge_token_req', (request, response) => {
let params = {
ssl_merchant_id: '*****',
ssl_user_id: '*****',
ssl_pin: '*****',
ssl_transaction_type: 'ccsale',
ssl_amount: '1.00'
}
axios({
method: 'post',
url: 'https://api.demo.convergepay.com/hosted-payments/transaction_token',
params: params
}).then((res) => { response.send(res.data)
}).catch((error) => {
console.log('there was an error getting transaction token: ',
error)
})
})
I've since found out the solution to my problem. The issue here is that converge expects a x-www-form-urlencoded string that needs to be Stringified before submitting the request. I found a library that works well for this called qs and I used it like so:
let params = qs.stringify({ // need this if content_type is application/x-www-form-urlencoded
ssl_merchant_id: env.CONVERGE.MERCHANT_ID,
ssl_user_id: env.CONVERGE.USER_ID,
ssl_pin: env.CONVERGE.PIN,
ssl_transaction_type: request.query.type,
ssl_amount: request.query.amount,
ssl_email: request.query.email,
ssl_company: request.query.company,
ssl_avs_address: request.query.address,
ssl_avs_zip: request.query.zip,
ssl_description: request.query.desc,
})
axios.post('https://api.convergepay.com/hosted-payments/transaction_token', params, {
headers: {
'Content_Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then((res) => {
response.send(res.data)
}).catch((error) => {
console.log('there was an error getting transaction token')
response.send(error.message)
})
I think you could also get away with just using JSON.stringify() but this way worked for me.

Resources