I'm trying to get the ean from this url: http://my_server.com/?ean=7038010034985
The NodeJS server handles the request like so:
const http = require('http')
const port = 3000
const requestHandler = async (request, response) => {
let bar_code = request.query.ean
bar_code = "7038010034985"
let product = await Promise.race([
get_info_meny_joker(bar_code, "meny.no"),
get_info_meny_joker(bar_code, "joker.no"),
get_info_openfoodfacts(bar_code)
])
// WRITE TO DATABASE
// database.ref('test/' + bar_code).set(product);
response.setHeader('Content-Type', 'application/json');
response.end(JSON.stringify(product))
}
const server = http.createServer(requestHandler)
server.listen(port, (err) => {
if (err) {
return console.log('Error occurred', err)
}
console.log(`Server is listening on ${port}`)
})
The application crashes (request.query.ean is undefined) as soon as it reaches "let bar_code = request.query.ean". I've googled around a bit, I just don't see what I'm doing different to the examples I've found. It worked just fine earlier when I was routing the request. Any ideas?
Full error message underneath (line and character places might be off because of heavily cutting code to post here)
0|index | TypeError: Cannot read property 'ean' of undefined
0|index | at Server.requestHandler (/home/ubuntu/kalori_app/server/index.js:32:34)
0|index | at emitTwo (events.js:126:13)
0|index | at Server.emit (events.js:214:7)
0|index | at Server.<anonymous> (/usr/local/lib/node_modules/pm2/node_modules/#pm2/io/build/main/metrics/httpMetrics.js:166:33)
0|index | at parserOnIncoming (_http_server.js:619:12)
0|index | at HTTPParser.parserOnHeadersComplete (_http_common.js:115:23)
You can use Node.js url API, it will parse everything for you:
const http = require('http'),
url = require('url'); // Import the library
const port = 3000
const requestHandler = async (request, response) => {
let bar_code = url.parse(request.url, true).query.ean; // Then use it
let product = await Promise.race([
get_info_meny_joker(bar_code, "meny.no"),
get_info_meny_joker(bar_code, "joker.no"),
get_info_openfoodfacts(bar_code)
])
// WRITE TO DATABASE
// database.ref('test/' + bar_code).set(product);
response.setHeader('Content-Type', 'application/json');
response.end(JSON.stringify(product))
}
const server = http.createServer(requestHandler)
server.listen(port, (err) => {
if (err) {
return console.log('Error occurred', err)
}
console.log(`Server is listening on ${port}`)
})
Read more about url API:
https://nodejs.org/api/url.html
Related
I want to send an array of strings over localhost 3000 with route start then send back a response with status 200 and eventually a map attached to response.body Currently i have this
Client code:
const axios = require('axios');
let listOfNames = ['mikey'];
axios.post(''http://localhost:3000/start'', {
data: { names: listOfNames }
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Server code:
const express = require('express');
const app = express()
const port = 3000
var listOfNames = [];
app.post('/start', async (req, res) => {
listOfNames = req.params.listOfNames;
res.status(200).send("Names added");
});
app.listen(port, () => {
console.log('request recieved');
});
I get this error presemably from how the request is being sent, any help?
TypeError [ERR_INVALID_URL]: Invalid URL
at new NodeError (node:internal/errors:393:5)
at URL.onParseError (node:internal/url:565:9)
at new URL (node:internal/url:645:5)
at dispatchHttpRequest (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:23
94:20)
at new Promise (<anonymous>)
at http (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:2330:10)
at Axios.dispatchRequest (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:
3260:10)
at Axios.request (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:3610:33)
at Axios.httpMethod [as post] (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios
.cjs:3649:19)
at Function.wrap [as post] (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cj
s:27:15) {
input: '/start',
code: 'ERR_INVALID_URL'
}
Edit: New error ECONNRESET error emerging from applied fixes
AxiosError: read ECONNRESET
at AxiosError.from (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:789:14
)
at RedirectableRequest.handleRequestError (C:\Users\cmb\rectangleHealth\node_modules\axios\dis
t\node\axios.cjs:2744:25)
at RedirectableRequest.emit (node:events:513:28)
at eventHandlers.<computed> (C:\Users\cmb\rectangleHealth\node_modules\follow-redirects\index.
js:14:24)
at ClientRequest.emit (node:events:513:28)
at Socket.socketErrorListener (node:_http_client:494:9)
at Socket.emit (node:events:513:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
syscall: 'read',
code: 'ECONNRESET',
errno: -4077,
The console also outputs a 2 json objects called request and config that cannot fit into this post.
I noticed 2 things errors in your code:
First, check your url is correct, instead of
''http://localhost:3000/start'' (you have multiple single quotes wrapping the url)
try,
"http://localhost:3000/start" or 'http://localhost:3000/start' (wrap it in proper double quotes or single quotes)
Second, You are passing the data in your api call as request body and not as request parameters, but you are trying to access it in the parameters of your api.
You should try accessing the request's body on the server side instead of parameters,
app.post('/start', async (req, res) => {
listOfNames = req.body.listOfNames;
res.status(200).send("Names added");
});
Else you might probably face issue while accessing the data in api as well.
I got an error every time Im trying to insert data into my MySQL database using the function router from express. It seems like my server try to send a response twice, but I do not know where.
Here is the error :
throw err; // Rethrow non-MySQL errors
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:526:11)
at ServerResponse.header (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\express\lib\response.js:267:15)
at Query.<anonymous> (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\src\bookingClient.js:24:36)
at Query.<anonymous> (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\mysql\lib\Connection.js:526:10)
at Query._callback (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\mysql\lib\Connection.js:488:16)
at Query.Sequence.end (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Query.ErrorPacket (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\mysql\lib\protocol\sequences\Query.js:92:8)
at Protocol._parsePacket (C:\Users\makia\Documents\PERSO\projets\elengi\salon-user\server\node_modules\mysql\lib\protocol\Protocol.js:291:23) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Here is my code:
const express = require('express');
function createRouter(db) {
const router = express.Router();
router.post('/bookings/createbookings', (req, res, next) => {
db.query(
'insert into booking (idHairdresser,idClient,date,note,status,time,slot,city,address,price) values (?,?,?,?,?,?,?,?,?,?)',
[req.body.idHairdresser, req.body.idClient, new Date (req.body.date), req.body.note, req.body.status, req.body.time, req.body.slot,req.body.city,req.body.address,req.body.price],
(error) => {
if (error) {
res.status(500).json({status: 'error'});
} else {
res.status(200).json({status: 'ok'});
}
}
);
});
return router;
}
module.exports = createRouter;
Here is source code where I connect my database, expressjs:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const hairdresser = require('./hairdresser');
const bookingHairdresser = require('./bookingHairdresser');
const bookingClient = require('./bookingClient');
const review = require('./review');
const prestation = require('./prestation');
const planning = require('./planning');
const connection = mysql.createConnection({
host : 'localhost',
user : 'user',
password : 'password',
database : 'database'
});
connection.connect();
const port = process.env.PORT || 8080;
const app = express()
.use(cors())
.use(bodyParser.json())
.use(bookingClient(connection))
.use(hairdresser(connection))
.use(bookingHairdresser(connection))
.use(review(connection))
.use(prestation(connection))
.use(planning(connection));
app.listen(port, () => {
console.log(`Express server listening on port ${port}`);
});
Here is the code I do on my client side :
createBookings(
booking: Booking){
return this.http.post(`${environment.serverUrl}/bookings/createbookings`, booking);
}
If you need more information, I can send the details of my source code. Thanks in advance for all your supports :)
The problem is that in you are sending the response multiple times. Please send details of source code so I can look into it
It clearly is a case of Middleware's taking you for a toss.
The error popped up in bookingClient.js:24.
The only possibility could be any router after bookingClient(hairdresser, bookingHairdresser, bookingHairdresser, review, presentation & planning) have a similar route '/bookings/createbookings'.
If yes, you might want to update your app.js as
app.use('PATH_PREFIX', bookingClient). Then, the paths inside bookingClient will become 'PATH_PREFIX/bookings/createbookings'.
app.js:
const express = require("express");
const https = require("https");
const app = express();
const port = 3000;
app.get("/",function(req,res){
const url ="https://maps.googleapis.com/maps/api/geocode/jsonaddress=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY;
console.log(response.statusCode);
response.on("data",function(data){
var jatin=JSON.parse(data);
console.log(jatin);
})
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
Error on Console
app.listen(3000,function(){ console.log("server started on port
3000"); })
server started on port 3000 200 undefined:26
"long_name"
SyntaxError: Unexpected end of JSON input
at JSON.parse ()
at IncomingMessage. (/home/jatin/Downloads/full_stack/Web-Development/maps/app.js:11:21)
at IncomingMessage.emit (events.js:189:13)
at IncomingMessage.Readable.read (_stream_readable.js:487:10)
at flow (_stream_readable.js:931:34)
at resume_ (_stream_readable.js:912:3)
at process._tickCallback (internal/process/next_tick.js:63:19) [nodemon] app crashed - waiting for file changes before starting
The output is visible when I run it on browser but on the console it throws an error.
For some reason JSON.parse() isn't working as expected.
I am trying to make a geocoding API call and in response, it gives me a JSON output...
which when I enter it as a URL on the browser the expected output is received
But when app.js is run on a node express server and when I hit my localhost:3000 I am getting the console error
Apparently the JSON.parse("data") is working but stops unexpectedly. Which leads to error.
You need to have your code to perform JSON.parse on end event instead, like this example form the documentation:
http.get('http://nodejs.org/dist/index.json', (res) => {
const { statusCode } = res;
const contentType = res.headers['content-type'];
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
// Consume response data to free up memory
res.resume();
return;
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
console.log(parsedData);
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
Notice that this is http.get, but it should be the same for https.get, so in your code the on('data') should be used to assemble the chunks before your perform JSON.parse() on it.
const express = require("express");
const https = require("https");
const app = express();
const port = 3000;
app.get("/", function(req, res) {
const url = "API_URL";
https.get(url, function(response) {
console.log(response.statusCode);
let body = "";
response.on("data", function(data) {
body += data;
});
response.on("end", function() {
console.log(JSON.parse(body));
});
});
res.end("End data response");
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
basically .on('end', callback') and .on('data', callback') are event listener to data receive and request end events, and to be able to handle your requests response in node when using http(s).get you have to attache an event listener on data event which is invoked every time your request receives a chunk of the request response, and once the request ended by the service the event end will be invoked stating that there is no more data from the server requested hence the request ended.
as stated in the documentation:
The callback must take care to consume the response data for reasons
stated in http.ClientRequest section.
const https = require("https");
const fs = require("fs");
const options = {
hostname: "en.wikipedia.org",
port: 443,
path: "/wiki/George_Washington",
method: "GET",
// ciphers: 'DES-CBC3-SHA'
};
const req = https.request(options, (res) => {
let responseBody = "";
console.log("Response started");
console.log(`Server Status: ${res.statusCode} `);
console.log(res.headers);
res.setEncoding("UTF-8");
res.once("data", (chunk) => {
console.log(chunk);
});
res.on("data", (chunk) => {
console.log(`--chunk-- ${chunk.length}`);
responseBody += chunk;
});
res.on("end", () => {
fs.writeFile("gw.html", responseBody, (err) => {
if (err) throw err;
console.log("Downloaded file");
});
});
});
req.on("error", (err) => {
console.log("Request problem", err);
});
returns
// Request problem { Error: socket hang up
// at createHangUpError (_http_client.js:330:15)
// at TLSSocket.socketOnEnd (_http_client.js:423:23)
// at TLSSocket.emit (events.js:165:20)
// at endReadableNT (_stream_readable.js:1101:12)
// at process._tickCallback (internal/process/next_tick.js:152:19) code: 'ECONNRESET' }
http.request() opens a new tunnel to the server. It returns a Writable stream which allows you to send data to the server, and the callback gets called with the stream that the server responds with. Now the error you encountered (ECONNRESET) basically means that the tunnel was closed. That usually happens when an error occured on a low level (very unlikely) or the tunnel timed out because no data was received. In your case the server only responded when you sent something to it, even if it was an empty package, so all you have to do is to end the stream, causing it to get flushed as an empty packet to the server, which causes it to respond:
req.end();
You might want to have a look at the request package which allows you to avoid dealing with such low-level things.
I have a set of tests to verify that my Express serves routes properly. For one of my routes launch.js, I receive two different errors, and sometimes the test randomly passes with long (425ms+) response times. Is there a better way to approach this?
launch.js
const authUtils = require('../../lib/authUtils');
const express = require('express');
const VError = require('verror');
const router = express.Router();
router.get('/', (req, res) => {
/**
* Request conformance object
*/
authUtils.getConformance((error, response, body) => {
// If error with HTTP request
if (error) {
throw new VError('Conformance object request failed', error);
// If error from auth server
} else if (response.body.message) {
throw new VError('Conformance object request failed', response.body.message);
// If request for conformance object succeeds
} else {
// Parse conformance object for tokenUri and authUri
authUtils.parseConformanceUris(body, (authUri, tokenUri, parsingError) => {
// Ensure URIs can be parsed from response
if (error) {
throw new VError('Issue while parsing conformance object', parsingError);
} else {
/**
* Data values needed later for /redirect
* #type {{state: string, tokenUri: string}}
*/
const launchData = {
state: authUtils.getUniqueCode(),
tokenUri,
};
// Build URI to request token from auth server
authUtils.buildGetTokenUri(authUri, launchData.state, (getTokenUri) => {
// Store state and tokenUri to session and redirect browser
authUtils.storeLaunchData(req, res, launchData, getTokenUri);
});
}
});
}
});
});
module.exports = router;
index.spec.js
const request = require('supertest');
const app = require('../index');
describe('Express server routes', () => {
describe('GET /launch', () => {
it('responds with HTTP 302', (done) => {
request(app).get('/launch').expect(302, done);
});
});
});
subject.getConformance
/**
* Utility function to request conformance object from auth server
* #param callback
*/
const getConformance = (callback) => {
request({ url: process.env.CONFORMANCE_URI, json: true, method: 'get' }, (error, response, body) => {
if (!error && response.statusCode === 200) {
callback(null, response, body);
} else {
callback(error, response, null);
}
});
};
Error 1
Uncaught TypeError: Cannot read property 'message' of null
at subject.getConformance (test/authUtils.spec.js:28:27)
at Request.request [as _callback] (lib/authUtils.js:7:374)
at Request.self.callback (node_modules/request/request.js:186:22)
at Request. (node_modules/request/request.js:1163:10)
at IncomingMessage. (node_modules/request/request.js:1085:12)
at endReadableNT (_stream_readable.js:1059:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
Error 2
Uncaught AssertionError: expected 'body' to equal undefined
at subject.getConformance (test/authUtils.spec.js:43:16)
at Request.request [as _callback] (lib/authUtils.js:7:374)
at Request.self.callback (node_modules/request/request.js:186:22)
at Request. (node_modules/request/request.js:1163:10)
at IncomingMessage. (node_modules/request/request.js:1085:12)
at endReadableNT (_stream_readable.js:1059:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
Assuming that the app object is requiring from a expressjs server, try
.get('/launch')
.expect(302)
.end(function (err, res) {
res.status.should.be.equal(302);
done();
});
If your index.js file is not a server then you need to configure the app object from a valid server. Are you exporting the app from index.js where app is
var express = require("express")
, app = express();
?