Node.js hangs on HTTP requests - node.js

I am currently developing an Electron application which listens to the TCP socket and sends requests to the REST server after receiving data.
For test purposes I use the following code:
const net = require('net');
const fetch = require('node-fetch');
const server = net.createServer(connection => {
connection.setEncoding('utf8');
connection.on('data', data => {
handleData(data).then(() => connection.end());
});
});
const handleData = data => {
return Promise.resolve()
.then(() => test(1))
.then(() => test(2))
.then(() => test(3))
.then(() => test(4))
.then(() => test(5));
};
const test = id => {
return fetch(`https://server.domain.name/api/v1/software/${id}`)
.then(response => response.json())
.then(json => {
console.log(json);
});
};
const socketHost = '0.0.0.0';
const socketPort = 1337;
server.listen(socketPort, socketHost);
This code hangs on the first request. According to the tcpdump, request does not even leave my machine. Strange thing is when I user IP address in URL instead of domain name, requests work fine. So, I suppose this problem is somehow related to DNS lookup. Any ideas?
Edit: When running this code in pure Node.js the issue does not appear.
Edit: This issue only appears on Linux.

Related

Using Native Fetch With Proxy in Node.js doesn't change my IP

I've upgraded my Node.js to the latest version which supports fetch natively. I'm trying to use a free public proxy to test, however when I'm making a request, it still comes from me directly. I know that because I'm calling an "Get my IP" service, and it returns my hope IP.
Here's the code example:
const HttpsProxyAgent = require('https-proxy-agent');
fetch(`https://api.ipify.org?format=json`, {agent: new HttpsProxyAgent("36.32.21.45:8085")})
.then(res => res.json()).then(res => console.log(res));
Tried putting proxy settings in the header as well this way:
const proxyAgent = require("proxy-agent");
(async () => {
const res = await fetch('https://api.ipify.org?format=json', {
headers: {
agent: new proxyAgent('http://80.48.119.28:8080'),
}
});
const data = await res.json();
console.log(data); //it shows my ip
})();
What am I missing?

How can I transfer data from Google CloudPlatform NodeJS app to BigQuery?

I have currently set up a NodeJS "server" on GoogleCloud Platform server where I am listening and receiving POST HTTP calls.
The body of each call contains a JSON that I would like to parse and transfer to Google BigQuery.
For now, this is the code I've created to receive the POST request:
"use strict";
const express = require("express");
const messages = [];
async function startServer() {
const app = express();
app.use(express.json());
app.post("/receive2", (req, res) => {
res.status(200).json({ message: req.body });
//Here I should manager the json contained in req.body
});
const PORT = process.env.PORT || 8080;
logger.info({ PORT }, "bonjour");
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
}
startServer();
The JSON is something similar to: https://gist.github.com/philipgiuliani/b63b22309d04048f0827
Yes, I am trying to save the receipts from In-App-Purchases made in my iOS app.
Can someone provide me a way to transfer the data of those receipts that I'm receiving to a BigQuery Table?
You can use NodeJS to append your csv data to a existing table or create a new table. I would recommend using Google Cloud Storage as a intermediate where you store the csv and simply point bigquery to the csv file which it should load. However you could also stream the data.
Stream:
let _count = await _BigQuery_
.dataset('dataset_name')
.table('table_name')
.query(`SELECT count(*) from table_name`)
.catch(e => console.error(e))
if (_count[0][0].count > 0)
console.log('no data')
Google Cloud Storage
Stream:
const gcs_file = Storage.file(gcs_path)
const gcs_write_stream = gcs_file.createWriteStream()
stream_from_csv_file
.on('error', (error) => {
gcs_write_stream.close()
})
.on('data', data => {
gcs_write_stream.write(row + '\r\n')
})
.on('end', function () {
gcs_write_stream.end();
loadFileToBigquery();
});
async function loadFIleToBigQuery(){
await _BigQuery_
.etl
.table('current_geoms_raw')
.load(gcs_file , {
sourceFormat: 'CSV',
skipLeadingRows: 1, // if headers are in csv
autodetect: false, // sometimes fails if true
location: 'US',
})
.catch(e => console.error(e))
}

How to fix an endpoint test that returns 404 status code rather than 200 using express, jest and supertest

My end goal is that I want to be able to create a test that satisfies the following statement:
verify that requests to valid URLs return a 200 HTTP status code
A valid URL for example would be /about-page or /jobs, basically any directory that I add in my content folder that contains a file with the extension /index.md.
This is my code so far:
app.js
const readFilePromise = util.promisify(fs.readFile)
app.get('/*', (req, res) => {
readFilePromise(path.join(__dirname, 'content', req.url) + '/index.md', 'utf8')
.then(data => {
convertData(data, res)
})
.catch(err => {
res.status(404).send('Page doesn\'t exist!')
})
})
const convertData = (data, res) => {
const convertedData = md.render(data)
readFilePromise(path.join(__dirname, '/template.html'), 'utf8')
.then(data => {
data = data.replace(/\{\{content\}\}/, convertedData)
res.send(data)
})
.catch(err => {
console.log(err)
})
}
app.listen(3000)
module.exports = app
After reading this article, it mentions that
Requests are asynchronous, which means you must be able to conduct asynchronous tests.
So I wrote the following test:
app.test.js
const app = require('./app.js')
const request = supertest(app)
const supertest = require('supertest')
it('Gets the test endpoint and returns a 200 status', async done => {
const res = await request.get('/*')
expect(res.status).toBe(200)
done()
})
When I run the test, it fails with a 404 status, rather than returning a 200 status. I thought this might be due to my app.js not being in the async/await style, so I changed app.js to:
const readFilePromise = util.promisify(fs.readFile)
app.get('/*', async (req, res) => {
try {
await readFilePromise(path.join(__dirname, 'content', req.url) + '/index.md', 'utf8')
} catch (err) {
res.status(404).send('Page doesn\'t exist!')
}
try {
const convertedData = md.render(data)
await readFilePromise(path.join(__dirname, '/template.html'), 'utf8')
data = data.replace(/\{\{content\}\}/, convertedData)
res.send(data)
} catch (err) {
console.log(err)
}
})
app.listen(3000)
module.exports = app
I tried running the test again, but it still fails with a 404. I think my set up within app.test.js is wrong, but I'm not sure exactly what, as I've tried using the various set ups as the article. How would I fix this?
Separately, when I try going to a URL using the async/await style in app.js, I get a ReferenceError: data is not defined error, but I'm not sure how to define data in the async/await format.
I explained here how to set up app for the test environment: supertest not found error testing express endpoint
You did not mention how you set the database environment, make sure your database is not empty. Then make your get request. but just checking status for get request is not enough because if your db is empty you will still get 200.
const response = await request(app).get("/route").send().expect(200);
expect(response.body.length).toBeGreaterThan(0)
Better approach would be connect to a different database, post your data first and then check the response
const response = await request(app).get("/api/tickets").send().expect(200);
expect(response.body.length).toEqual(2); // if you post two items
Also before you every test make sure you start with empty database inside beforeEach()

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.

create server with node and get endpoint with React Native

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.

Resources