create server with node and get endpoint with React Native - node.js

I have json file and created node.js server to set endpoint and then get this data via my React Native application. If I'm not wrong it worked correctly in friday but I had to mess something up and now I totally don't know how to fix it. All time I get error:
Possible Unhandled Promise Rejection (id: 0): TypeError: Network
request failed
self.fetch/http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:27859:18
dispatchEvent#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:29144:13
setReadyState#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:28897:15
__didCompleteResponse#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:28724:11
send/<#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:28834:18
emit#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:4538:15
__callFunction#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:2608:22
callFunctionReturnFlushedQueue/<#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:2385:11
__guard#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:2561:13
callFunctionReturnFlushedQueue#blob:http://192.168.1.39:8081/1c49a23b-7fbb-c640-a946-c1e001192c92:2384:9
onmessage#http://192.168.1.39:8081/debugger-ui/debuggerWorker.js:72:25
my Node server:
const filename = './logos.json';
const server = http.createServer((req, res) => {
if (req.url === "/logo") {
res.writeHead(200, { "Content-Type": "application/json" });
fs.createReadStream(__dirname + "/logos.json").pipe(res)
}
})
server.listen(3000, (err) => {
if (err) throw err;
console.log('server is listening on port 3000');
})
and my RN code :
syncLogoData = () => {
fetch('http://localhost:3000/logo')
.then(resp => resp.json())
.then(data => console.log(data))
.catch(err => console.log(err))
}

Looks like you're trying to run this on a device. The device doesn't know localhost points to your server. In your syncLogoData, change the uri to http://ip_address:3000/logo and it should work.
Also helpful to open http://localhost:3000/logo on your computer browser to make sure your server code is correct.

Related

PayFast integration in NodeJS / ReactJS

I am trying to integrate PayFast into my React / NodeJS app. Using Express, my NodeJS successfully retrieves a payment uuid from the PayFast endpoint (I see this uuid in my console log) -
app.get("/api", async (req, res) => {
paymentData["signature"] = generateSignature(paymentData, phrase);
console.log(paymentData["signature"])
const str = dataToString(paymentData)
const id = await getPaymentId(str)
res.json({uuid: id})
})
However, in my front end (ReactJS) I am getting an undefined response & possible CORS issue from my backend API end point when trying to retrieve this uuid -
My custom fetch hook:
export default function useFetch(baseUrl) {
const [loading, setLoading] = useState(true);
function get() {
return new Promise((resolve, reject) => {
fetch(baseUrl)
.then(res => {
console.log(res)
res.json()
})
.then(data => {
console.log(data);
if (!data) {
setLoading(false);
return reject(data);
}
setLoading(false);
resolve(data);
})
.catch(error => {
setLoading(false);
reject(error);
});
});
}
return { get, loading };
};
The error:
Response {type: 'cors', url: 'http://localhost:3001/api', redirected: false, status: 200, ok: true, …}
undefined
If I test my NodeJS end point from my browser, it successfully comes back with my payment uuid. Any one have any ideas why my React app is acting up?
Update your CORS config to accept connections from the React app host.
app.use(cors({
origin: 'http://localhost:3000',
}));
Open package.json of your react app and add a line on the bottom of the json file:
"proxy":"http://localhost:3001"
3001 is the PORT that your Node http server is running on locally, if it's another PORT just change it accordingly.
This will redirect all http traffic from your webpack dev server running on PORT 3000, to your Node server running on 3001.
For those others who might encounter a similar type of an issue, I have attached a blog post with the method that I have used to solve the CORS issue, as well as integrate with the PayFast API.
https://codersconcepts.blogspot.com/2022/04/nodejs-payfast-integration.html

Network Request Failed while Integrating React Native(using Expo) to Node js

I developed a React Native app and then i devloped Node js as a backend and write all the required REST apis.
But whenever i tried to fetch data from my backend it says Network Request Failed
I am starting my web server using command :-
npm start --host 0.0.0.0
And then i am checking whether i'm getting data from server or not by typing my ip address : port in the browser of both my android phone and laptop and there i'm getting my data.
But i don't know why is my react native app unable to fetch data...
My code is :-
export const fetchDishes = () => (dispatch) => {
dispatch(dishesLoading(true));
console.log("baseUrl", baseUrl);
return fetch('https://192.168.43.182:3443/dishes')
.then(response => {
if (response.ok) {
return response;
}
else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(dishes => dispatch(addDishes(dishes)))
.catch(error => dispatch(dishesFailed(error.message)));
}
export const dishesLoading = () => ({
type: ActionTypes.DISHES_LOADING
});
export const dishesFailed = (errmess) => ({
type: ActionTypes.DISHES_FAILED,
payload: errmess
});
export const addDishes = (dishes) => ({
type: ActionTypes.ADD_DISHES,
payload: dishes
});
As u can see i have put the same ip and port in the fetch() method and still getting Network Request Failed error.
Note:- I am running app on my physical device
Edit - My app is successfully fetching data on http but gives error in https.

How to deal with backend dynamically allocated ports on react.js side using axios?

This morning I deployed a MERN stack login app in heroku successfully. But, when I tried to login
GET http://localhost:5000/user/login/email/password net::ERR_CONNECTION_REFUSED
in the console.
I understood that that the error is because I am making get request in axios using
axios.get("http://localhost:5000/user/login/" + this.state.email + "/" + this.state.password).then((res) => {
if (res.status === 200) {
this.setState({ status: res.status, name: res.data.name });
console.log(res.data);
}
else
throw new Error(res.status);
}).catch((err) => {
this.setState({ isInvalid: true });
})
But, the port is being dynamically allocated on the server side.
const port = process.env.PORT||5000;
app.listen(port, () => {
console.log("Server started on port:" + port);
});
Tried allocating only hardcoded value to the port. Still no luck
There are lots of mistakes in your code. You have deployed your app but your URL is still localhost which is not Heroku URL. First of all you need to setup env variables for your application like this.
You can put this in some constant file from where you get your end point. Don't write END POINTS directly in the ajax calls. Use constant and create a single file for from where you do all the ajax calls of the application.
You can set the env for both frontend and backend and this is how you should work. The development env should be separate from production one.
if (process.env.NODE_ENV === "development") {
API = "http://localhost:8000";
} else if (process.env.NODE_ENV === "production") {
API = "https://be-prepared-app-bk.herokuapp.com";
}
Don't use GET for the login and sending email and password in parameters. You should use POST and send all the data in body.
Here's how you single ajax file should look alike:
import { API_HOST } from "./constants";
import * as auth from "../services/Session";
const GlobalAPISvc = (endPoint, method, data) => {
const token = auth.getItem("token");
const uuid = auth.getItem("uuid");
return new Promise((resolve, reject) => {
fetch(`${API_HOST}${endPoint}`, {
method: method,
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
"x-authentication": token,
uuid: uuid
}
})
.then(res => {
return res.json();
})
.then(json => {
resolve(json);
})
.catch(error => {
reject(error);
});
}).catch(error => {
return error;
});
};
export default GlobalAPISvc;
I have created an application in MERN which I made public on GitHub. Feel free to take help from that. Repository Link
Firstly, I would suggest you, not to use get request method for login.
Secondly, if you've deployed your backend code then use dynamic url provided by heroku for login request.
e.g. if your url is xyz.heroku.com then axios.get('xyz.heroku.com/user/login/'+email+'/'+password);
as now you don't need to hard-code the port or use localhost.

Can't connect to service when using consul for service discovery | Node.js

I am working on creating an API gateway and so far I can manage to get everything to work for single instances where I hard code the IP and port of the server I want my API gateway to connect to.
I have seen few examples of how to accomplish service discovery with Consul/Node.js.
I did find this one and I have tried to make it work but I can't get the watcher to work right and pass me the IP:port combo I need to connect to the service.
All of the below files are just parts and not the whole thing. The important parts are there though.
This is my app.js file
app.listen(port, () => {
const CONSUL_ID = require('uuid').v4();
const ip = require('ip');
const my_IP = ip.address();
let options = {
name: 'api-gateway',
address: `${my_IP}`,
port: 8080,
id: CONSUL_ID,
check: {
ttl: '10s',
deregister_critical_service_after: '1m'
}
};
consul.agent.service.register(options, function(err) {
if (err) throw err;
console.log(`Registered service with ID of ${CONSUL_ID}`);
});
setInterval(() => {
consul.agent.check.pass({id:`service:${CONSUL_ID}`}, err => {
if (err) throw new Error(err);
});
}, 5 * 1000);
process.on('SIGINT', () => {
console.log(`SIGINT. De-Registering service with ID of ${CONSUL_ID}`);
consul.agent.service.deregister(CONSUL_ID, (err) => {
if(err) console.log(`Error de-registering service from consul, with error of : ${err}`);
if(!err) console.log(`De-registered service with ID of ${CONSUL_ID}`);
process.exit();
});
});
console.log(`API gateway server running express started on port ${port}.`);
});
I have two other test services running that the only difference between my app.js above and these test ones are that they have name: 'test-service', for the service name.
This is my routes file
var consul = require("consul")({host: '10.0.1.248'});
var known_data_instances = [];
const apiAdapter = require('./apiAdapter')
// Keep a list of healthy services
var watcher = consul.watch({
method: consul.health.service,
options: {
service:'test-service',
passing:true
}
});
watcher.on('change', data => {
console.log('received discovery update:', data.length);
known_data_instances = [];
data.forEach(entry => {
known_data_instances.push(`http://${entry.Service.Address}:${entry.Service.Port}/`);
});
});
watcher.on('error', err => {
console.error('watch error', err);
});
const BASE_URL = known_data_instances[Math.floor(Math.random()*known_data_instances.length)];
// const api = apiAdapter(BASE_URL + ':8081');
const api = apiAdapter(BASE_URL);
// router.get('/login', isAuthorized, (req, res) => {
router.get('/login', (req, res) => {
api.get(req.path).then(resp => {
res.send(resp.data);
});
});
API adapter file
const axios = require('axios');
module.exports = (baseURL) => {
return axios.create({
baseURL: baseURL,
});
};
I am expecting to be able to send a request using axios to a HTTP endpoint on a different service on a different server when getting the IP and port from consul.
Actual result is:
(node:3230) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14)
Seems to me like it is not picking up the URLs and is defaulting back onto localhost port 80.
I'm a bit lost on all of this since I have never build an application with consul and while the consul.io docs are great, there just isn't much of a guide base online for making this easy to learn.
Guess the question comes down to, how do I get my api adapter to make requests to my different services, in this case test-service?

Cant create soap client on node

When accessing WSDL api via another tool it is working but when i try to create a client via node it gives this error.
{ [Error: Parse Error] bytesParsed: 161, code:
'HPE_INVALID_HEADER_TOKEN' }
Code i am using
var url = 'https://payments.jazzcash.com.pk/PayAxisExternalStatusService/StatusService_v11.svc?wsdl';
soap.createClient(url, function(err, client) {
console.log(err);
console.log(client); })
Using node module soap
You might need to use https://www.npmjs.com/package/http-parser-js
1 npm install http-parser-js
2 Insert this code before require('soap')
process.binding('http_parser').HTTPParser = require('http-parser-js').HTTPParser;
Following above steps will fix your issue
Node.js is really strict about response format of the server.
I tried http-parser-js but it is very sensitive to the version of Node.js you use.
If you need to communicate with the server which sends malformed responses the only way I see is to use sockets:
const net = require('net');
const socketConnection = net.createConnection('80', 'google.com');
socketConnection.on('data', (data) => {
console.log('SOCKET RESPONSE', data.toString());
}).on('connect', () => {
const request = "GET / HTTP/1.1\r\n"
+ "Accept: */*\r\n\r\n";
socketConnection.write(request);
console.log('request sent');
}).on('end', () => {
console.log('the end');
}).on('error', (error) => {
console.log('connection error:', error);
});
In the context of the SOAP client, you can get WSDL yourself and store it locally and then create a SOAP client.

Resources