nodejs: missing ) after argument list - node.js

When I run nodejs http_test.js, which is attached following, it appeared "missing ) after argument list", I check the "(" and "{" but felt nothing wrong. help!
const http = require('http');
http.get({
hostname: 'localhost',
port: 5000,
path: '/123/',
agent: false // create a new agent just for this one request
}, (res) => {
console.log(res)
// Do stuff with response
})

Per #aaron-dufour's comment above, you are probably trying to run that code in an interpreter that does not support ECMAScript 6.
If changing the contents of the file to the following works, then that's your problem:
var http = require('http');
http.get({
hostname: 'localhost',
port: 5000,
path: '/123/',
agent: false // create a new agent just for this one request
}, function(res) {
console.log(res)
// Do stuff with response
});
In your case, you are using Nodejs, which should be okay, given this article. It may be that you are using a significantly out of date version. Try running node -v or node --version to see what version you're running.

Related

How to move an #hapi plugin out to its own separate file

I am upgrading the Node version of my system and have got to the point of updating hapi to #hapi/hapi. I am using Node version 14.0.0 and #hapi/hapi version 20.2.2
I've written a simple server with just one route, which works perfectly:
'use strict';
const Hapi = require('#hapi/hapi');
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
// await server.register(require('./plugins'))
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello World!';
}
});
await server.start();
console.log(`'Test' server running on Node ${process.version} at:`, server.info.uri);
};
init();
However, if I uncomment the server.register call and comment out the server.route code I get an error. The file ./plugins/index.js looks like this:
'use strict';
const report = {
name: 'report',
version: '1.0.0',
register: async function (server, options) {
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello World!';
}
});
}
}
The error I am getting from the #hapi server is this:
(node:4793) UnhandledPromiseRejectionWarning: Error: Invalid plugin options {
"plugin": {
"register" [1]: -- missing --
}
}
[1] "plugin.register" is required
It looks like a very simple issue, but I cannot find anything relatively modern on the Internet to help me out. Please can someone just point me in the right direction? - thank you.
EDITED: I have moved #hapi/hapi up to the latest version, 21.1.0, and Node up to 18.12.1 but still get the same message.

What is similar to -k / --insecure of CURL for Nodejs? [duplicate]

I'm working on a little app that logs into my local wireless router (Linksys) but I'm running into a problem with the router's self-signed ssl certificate.
I ran wget 192.168.1.1 and get:
ERROR: cannot verify 192.168.1.1's certificate, issued by `/C=US/ST=California/L=Irvine/O=Cisco-Linksys, LLC/OU=Division/CN=Linksys/emailAddress=support#linksys.com':
Self-signed certificate encountered.
ERROR: certificate common name `Linksys' doesn't match requested host name `192.168.1.1'.
To connect to 192.168.1.1 insecurely, use `--no-check-certificate'.
In node, the error being caught is:
{ [Error: socket hang up] code: 'ECONNRESET' }
My current sample code is:
var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
method: 'GET'
}, function(res){
var body = [];
res.on('data', function(data){
body.push(data);
});
res.on('end', function(){
console.log( body.join('') );
});
});
req.end();
req.on('error', function(err){
console.log(err);
});
How can I go about getting node.js to do the equivalent of "--no-check-certificate"?
Cheap and insecure answer:
Add
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
in code, before calling https.request()
A more secure way (the solution above makes the whole node process insecure) is answered in this question
In your request options, try including the following:
var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
method: 'GET',
rejectUnauthorized: false,
requestCert: true,
agent: false
},
Don't believe all those who try to mislead you.
In your request, just add:
ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})]
If you turn on unauthorized certificates, you will not be protected at all (exposed to MITM for not validating identity), and working without SSL won't be a big difference. The solution is to specify the CA certificate that you expect as shown in the next snippet. Make sure that the common name of the certificate is identical to the address you called in the request(As specified in the host):
What you will get then is:
var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})],
method: 'GET',
rejectUnauthorized: true,
requestCert: true,
agent: false
},
Please read this article (disclosure: blog post written by this answer's author) here in order to understand:
How CA Certificates work
How to generate CA Certs for testing easily in order to simulate production environment
Add the following environment variable:
NODE_TLS_REJECT_UNAUTHORIZED=0
e.g. with export:
export NODE_TLS_REJECT_UNAUTHORIZED=0
(with great thanks to Juanra)
Adding to #Armand answer:
Add the following environment variable:
NODE_TLS_REJECT_UNAUTHORIZED=0 e.g. with export:
export NODE_TLS_REJECT_UNAUTHORIZED=0 (with great thanks to Juanra)
If you on windows usage:
set NODE_TLS_REJECT_UNAUTHORIZED=0
Thanks to: #weagle08
You can also create a request instance with default options:
require('request').defaults({ rejectUnauthorized: false })
For meteorJS you can set with npmRequestOptions.
HTTP.post(url, {
npmRequestOptions: {
rejectUnauthorized: false // TODO remove when deploy
},
timeout: 30000, // 30s
data: xml
}, function(error, result) {
console.log('error: ' + error);
console.log('resultXml: ' + result);
});
try
export NODE_TLS_REJECT_UNAUTHORIZED=0
Or you can try to add in local name resolution (hosts file found in the directory etc in most operating systems, details differ) something like this:
192.168.1.1 Linksys
and next
var req = https.request({
host: 'Linksys',
port: 443,
path: '/',
method: 'GET'
...
will work.
So, my company just switched to Node.js v12.x.
I was using NODE_TLS_REJECT_UNAUTHORIZED, and it stopped working.
After some digging, I started using NODE_EXTRA_CA_CERTS=A_FILE_IN_OUR_PROJECT that has a PEM format of our self signed cert and all my scripts are working again.
So, if your project has self signed certs, perhaps this env var will help you.
Ref: https://nodejs.org/api/cli.html#cli_node_extra_ca_certs_file
In case you are looking for posting using #nestjs/axios,
here is the syntax without certificate (Non Production Solution):
const token = Buffer.from(`${user}:${password}`,'utf8').toString('base64')
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${token}`,
},
httpsAgent: new https.Agent({
rejectUnauthorized: false
}),
};
const responseData = await firstValueFrom(
this.httpService.post(url, data, config).pipe(map((response) => response.data)),
);
here is the syntax with certificate (Production Solution):
const token = Buffer.from(`${user}:${password}`,'utf8').toString('base64')
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${token}`,
},
httpsAgent: new https.Agent({
rejectUnauthorized: true,
ca: fs.readFileSync(path.join(__dirname, './resources/certificateName'))
}),
};
const responseData = await firstValueFrom(
this.httpService.post(url, data, config).pipe(map((response) => response.data)),
);
When you cannot control the request creation
When using packages you sometimes don't have the option to set the correct settings on the request call, nor does the package offer you a way to inject a request.
However you might still want to avoid the insecure NODE_TLS_REJECT_UNAUTHORIZED=0 and opt for only having an insecure connection to a specified target.
This is how I solved the issue:
// check if host and port fit your application
function isSelf(host, port) {
return host === myHost && port === myPort;
}
// get the built in tls module and overwrite the default connect behavior
const tls = require("tls");
const _connect = tls.connect;
function wrappedConnect(options, secureConnectListener) {
if (isSelf(options.host, options.port)) {
options.rejectUnauthorized = false;
}
return _connect(options, secureConnectListener);
}
tls.connect = wrappedConnect;

How to add an SSL certificate (ca-cert) to node.js environment variables in order to connect to Digital Ocean Postgres Managed Database?

I am currently using node-postgres to create my pool. This is my current code:
const { Pool } = require('pg')
const pgPool = new Pool({
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
port: process.env.PGPORT,
ssl: {
rejectUnauthorized: true,
// Would like to add line below
// ca: process.env.CACERT,
},
})
I found another post where they read in the cert using 'fs' which can be seen below.
const config = {
database: 'database-name',
host: 'host-or-ip',
user: 'username',
password: 'password',
port: 1234,
// this object will be passed to the TLSSocket constructor
ssl: {
ca: fs.readFileSync('/path/to/digitalOcean/certificate.crt').toString()
}
}
I am unable to do that as I am using git to deploy my application. Specifically Digital Oceans new App Platform. I have attempted reaching out to them with no success. I would prefer not to commit my certificate in my source control. I see a lot of posts of people suggesting to set
ssl : { rejectUnauthorized: false}
That is not the approach I want to take. My code does work with that but I want it to be secure.
Any help is appreciated thanks.
Alright I finally was able to figure it out. I think the issue was multiline and just unfamiliarity with dotenv for my local developing environment.
I was able to get it all working with my code like this. It also worked with the fs.readFileSync() but I didn't want to commit that to my source control.
const { Pool } = require('pg')
const fs = require('fs')
const pgPool = new Pool({
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
port: process.env.PGPORT,
ssl: {
rejectUnauthorized: true,
// ca: fs.readFileSync(
// `${process.cwd()}/cert/ca-certificate.crt`.toString()
// ),
ca: process.env.CA_CERT,
},
})
.on('connect', () => {
console.log('connected to the database!')
})
.on('error', (err) => {
console.log('error connecting to database ', err)
})
Now in my config.env I had to make it look like this:
CA_CERT="-----BEGIN CERTIFICATE-----\nVALUES HERE WITH NO SPACES AND A \n
AFTER EACH LINE\n-----END CERTIFICATE-----"
I had to keep it as a single line string to have it work. But I was finally to connect with
{rejectUnauthorized:true}
For the digital ocean app platform environment variable, I copied everything including the double quotes and pasted it in there. Seems to work great. I do not think you will be able to have this setting set to true with their $7 development database though. I had to upgrade to the managed one in order to find any CA cert to download.

res.render doesn't render correctly after 1023 characters

I have a parent Express app, and a Ghost app as a child app, using Ghost as an npm module here.
I routed Ghost to be rendered at http://localhost:9000/blog. All the configuration works fine (Ghost will throw an error if the basic configuration isn't being provided correctly).
Here is my Ghost startup code
ghost({
config: path.join(__dirname, '/config/ghost.config.js')
}).then(function (ghostServer) {
app.use(ghostServer.config.paths.subdir, ghostServer.rootApp);
ghostServer.start(app);
});
here is my Ghost config
// # Ghost Configuration
// Setup your Ghost install for various [environments](http://support.ghost.org/config/#about-environments).
// Ghost runs in `development` mode by default. Full documentation can be found at http://support.ghost.org/config/
var path = require('path'),
config;
config = {
// ### Production
// When running Ghost in the wild, use the production environment.
// Configure your URL and mail settings here
production: {
url: 'http://my-ghost-blog.com',
mail: {},
database: {
client: 'sqlite3',
connection: {
filename: path.join(__dirname, '/content/data/ghost.db')
},
debug: false
},
server: {
host: '127.0.0.1',
port: '2368'
}
},
// ### Development **(default)**
development: {
// The url to use when providing links to the site, E.g. in RSS and email.
// Change this to your Ghost blog's published URL.
url: 'http://localhost:9000/blog/',
// Example mail config
// Visit http://support.ghost.org/mail for instructions
// ```
// mail: {
// transport: 'SMTP',
// options: {
// service: 'Mailgun',
// auth: {
// user: '', // mailgun username
// pass: '' // mailgun password
// }
// }
// },
// ```
// #### Database
// Ghost supports sqlite3 (default), MySQL & PostgreSQL
database: {
client: 'sqlite3',
connection: {
filename: path.join(__dirname, '../blog/data/ghost-dev.db')
},
debug: false
},
// #### Server
// Can be host & port (default), or socket
server: {
// Host to be passed to node's `net.Server#listen()`
host: '127.0.0.1',
// Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
port: '9000'
},
// #### Paths
// Specify where your content directory lives
paths: {
contentPath: path.join(__dirname, '../blog/')
}
},
// **Developers only need to edit below here**
// ### Testing
// Used when developing Ghost to run tests and check the health of Ghost
// Uses a different port number
testing: {
url: 'http://127.0.0.1:2369',
database: {
client: 'sqlite3',
connection: {
filename: path.join(__dirname, '/content/data/ghost-test.db')
}
},
server: {
host: '127.0.0.1',
port: '2369'
},
logging: false
},
// ### Testing MySQL
// Used by Travis - Automated testing run through GitHub
'testing-mysql': {
url: 'http://127.0.0.1:2369',
database: {
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'root',
password : '',
database : 'ghost_testing',
charset : 'utf8'
}
},
server: {
host: '127.0.0.1',
port: '2369'
},
logging: false
},
// ### Testing pg
// Used by Travis - Automated testing run through GitHub
'testing-pg': {
url: 'http://127.0.0.1:2369',
database: {
client: 'pg',
connection: {
host : '127.0.0.1',
user : 'postgres',
password : '',
database : 'ghost_testing',
charset : 'utf8'
}
},
server: {
host: '127.0.0.1',
port: '2369'
},
logging: false
}
};
module.exports = config;
So basically, when I go to http://localhost:9000/blog, it isn't being rendered at all. Nothing. I was using Chrome and also testing it using Safari. Also tested those two without JavaScript turned on.
And then I try to do curl http://localhost:9000/blog, and try using a requester app (like Postman) and they returned the correct html string. I also tried to do a curl using the user agent as Chrome and as Safari, it also returns the correct html.
I traced down to ghost node_modules, and the renderer is in ghost > core > server > controllers > frontend > index.js in this line res.render(view, result)
I changed the res.render to be like this
res.render(view, result, function(err, string) {
console.log("ERR", err);
console.log("String", string);
res.send(string);
})
and there is no error, it logs the current string, but it doesn't render anything on the browser.
I tried curl, postman, works, but browser doesn't work.
then I tried to send a hello world string, it works, the browser rendered it.
Then I add the string length one by one, and it turns out, any str.length < 1023 will be able to be rendered by the browser, but once it get past that, it doesn't.
And I tried in my parent Express app, it is able to send string which length is more than 1023, and if I use the ghost module as a standalone, it also able to send string more than 1023.
So something must have happened between those two, but I don't know how to debug this.
Please help

Ignore invalid self-signed ssl certificate in node.js with https.request?

I'm working on a little app that logs into my local wireless router (Linksys) but I'm running into a problem with the router's self-signed ssl certificate.
I ran wget 192.168.1.1 and get:
ERROR: cannot verify 192.168.1.1's certificate, issued by `/C=US/ST=California/L=Irvine/O=Cisco-Linksys, LLC/OU=Division/CN=Linksys/emailAddress=support#linksys.com':
Self-signed certificate encountered.
ERROR: certificate common name `Linksys' doesn't match requested host name `192.168.1.1'.
To connect to 192.168.1.1 insecurely, use `--no-check-certificate'.
In node, the error being caught is:
{ [Error: socket hang up] code: 'ECONNRESET' }
My current sample code is:
var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
method: 'GET'
}, function(res){
var body = [];
res.on('data', function(data){
body.push(data);
});
res.on('end', function(){
console.log( body.join('') );
});
});
req.end();
req.on('error', function(err){
console.log(err);
});
How can I go about getting node.js to do the equivalent of "--no-check-certificate"?
Cheap and insecure answer:
Add
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
in code, before calling https.request()
A more secure way (the solution above makes the whole node process insecure) is answered in this question
In your request options, try including the following:
var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
method: 'GET',
rejectUnauthorized: false,
requestCert: true,
agent: false
},
Don't believe all those who try to mislead you.
In your request, just add:
ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})]
If you turn on unauthorized certificates, you will not be protected at all (exposed to MITM for not validating identity), and working without SSL won't be a big difference. The solution is to specify the CA certificate that you expect as shown in the next snippet. Make sure that the common name of the certificate is identical to the address you called in the request(As specified in the host):
What you will get then is:
var req = https.request({
host: '192.168.1.1',
port: 443,
path: '/',
ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})],
method: 'GET',
rejectUnauthorized: true,
requestCert: true,
agent: false
},
Please read this article (disclosure: blog post written by this answer's author) here in order to understand:
How CA Certificates work
How to generate CA Certs for testing easily in order to simulate production environment
Add the following environment variable:
NODE_TLS_REJECT_UNAUTHORIZED=0
e.g. with export:
export NODE_TLS_REJECT_UNAUTHORIZED=0
(with great thanks to Juanra)
Adding to #Armand answer:
Add the following environment variable:
NODE_TLS_REJECT_UNAUTHORIZED=0 e.g. with export:
export NODE_TLS_REJECT_UNAUTHORIZED=0 (with great thanks to Juanra)
If you on windows usage:
set NODE_TLS_REJECT_UNAUTHORIZED=0
Thanks to: #weagle08
You can also create a request instance with default options:
require('request').defaults({ rejectUnauthorized: false })
For meteorJS you can set with npmRequestOptions.
HTTP.post(url, {
npmRequestOptions: {
rejectUnauthorized: false // TODO remove when deploy
},
timeout: 30000, // 30s
data: xml
}, function(error, result) {
console.log('error: ' + error);
console.log('resultXml: ' + result);
});
try
export NODE_TLS_REJECT_UNAUTHORIZED=0
Or you can try to add in local name resolution (hosts file found in the directory etc in most operating systems, details differ) something like this:
192.168.1.1 Linksys
and next
var req = https.request({
host: 'Linksys',
port: 443,
path: '/',
method: 'GET'
...
will work.
So, my company just switched to Node.js v12.x.
I was using NODE_TLS_REJECT_UNAUTHORIZED, and it stopped working.
After some digging, I started using NODE_EXTRA_CA_CERTS=A_FILE_IN_OUR_PROJECT that has a PEM format of our self signed cert and all my scripts are working again.
So, if your project has self signed certs, perhaps this env var will help you.
Ref: https://nodejs.org/api/cli.html#cli_node_extra_ca_certs_file
In case you are looking for posting using #nestjs/axios,
here is the syntax without certificate (Non Production Solution):
const token = Buffer.from(`${user}:${password}`,'utf8').toString('base64')
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${token}`,
},
httpsAgent: new https.Agent({
rejectUnauthorized: false
}),
};
const responseData = await firstValueFrom(
this.httpService.post(url, data, config).pipe(map((response) => response.data)),
);
here is the syntax with certificate (Production Solution):
const token = Buffer.from(`${user}:${password}`,'utf8').toString('base64')
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${token}`,
},
httpsAgent: new https.Agent({
rejectUnauthorized: true,
ca: fs.readFileSync(path.join(__dirname, './resources/certificateName'))
}),
};
const responseData = await firstValueFrom(
this.httpService.post(url, data, config).pipe(map((response) => response.data)),
);
When you cannot control the request creation
When using packages you sometimes don't have the option to set the correct settings on the request call, nor does the package offer you a way to inject a request.
However you might still want to avoid the insecure NODE_TLS_REJECT_UNAUTHORIZED=0 and opt for only having an insecure connection to a specified target.
This is how I solved the issue:
// check if host and port fit your application
function isSelf(host, port) {
return host === myHost && port === myPort;
}
// get the built in tls module and overwrite the default connect behavior
const tls = require("tls");
const _connect = tls.connect;
function wrappedConnect(options, secureConnectListener) {
if (isSelf(options.host, options.port)) {
options.rejectUnauthorized = false;
}
return _connect(options, secureConnectListener);
}
tls.connect = wrappedConnect;

Resources