Setup Node.js HTTPS to work with HAPROXY - javascript

I'm trying to make my nodejs app to communicate with HAPROXY via https. The idea is that nodejs sends message to haproxy via https, haproxy routes message forward.
I used request.js library and all worked fine, but now I need to perform this task without any libraries. The scenario is following. If environment variable is 1, I should use HTTP, in other cases -HTTPS. The problem is that when I use https and haproxy, I get "Socket hangup error", but everything works fine with request.js. Here is my code.
const protocol = process.env.NODE_ENV === 1 ? require('http') : require('https');
then I configure HTTPS
this.api = url.parse(app.get('API_HAPROXY'));
this.options = {
port: this.api.port,
hostname: this.api.hostname,
path: '/api/report',
method: 'POST',
headers: {
"Content-Type": "application/json",
},
rejectUnauthorized: false,
requestCert: true,
agent: false
};
Because I don't want to use ca to validate ssh keys I use NODE_TLS_REJECT_UNAUTHORIZED=0
reportData(json) {
const req = protocol.request(this.options, (res) => {
res.on('error', (err) => {
this.logger.error(`Failed to report ${err.message}`)
})
});
req.write(JSON.stringify(json));
req.end();
req.on('error', (err) => {
this.logger.error(`Failed to report ${err.message}`);
});
}
In this case I get socket hangup error while using HTTPS
Here is my request configuration
request({
uri: `${this.api}/api/report`,
method: 'POST',
json,
}, (err, response) => {
if (err || response.statusCode !== 200) {
this.logger.error(`Failed to report : ${err ? err.message : response.statusCode}`);
} else {
this.logger.info(`Report was sent`);
}
});

The issue was fixed by adding content-length header to the options.headers.
this.api = url.parse(app.get('API_HAPROXY')); this.options = {
port: this.api.port,
hostname: this.api.hostname,
path: '/api/report',
method: 'POST',
headers: {
"Content-Type": "application/json",
"Content-Length: <calculated length of the object you want to send in bytes >
},
rejectUnauthorized: false,
requestCert: true,
agent: false
};

Related

Forbidden error fetch API from client to server(vanilla js as client and nestjs as backend)

I have issue with call online API from client.
I created nestjs API with httponly credential and when
nestjs app hosted in local and client from local it's worked
also when nestjs app hosted in online server and client hosted in online server it's worked
but when nestjs hosted in online server and client call API from local get forbidden error.
nestjs main.ts:
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '#nestjs/common';
// eslint-disable-next-line #typescript-eslint/no-var-requires
const cookieSession = require('cookie-session');
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
credentials:true,
origin:['http://localhost:3000','http://test.nextu.top']
});
app.use(
cookieSession({
keys: ['asdasd'],
}),
);
app.useGlobalPipes(new ValidationPipe());
await app.listen(5072);
}
bootstrap();
client fetch:
const doLogin = async () => {
const bData = {
Email: '********',
Password: '****'
}
fetch("http://api.nextu.top:5072/auth/signin", {
method: "POST",
body: JSON.stringify(bData),
headers: {
"access-control-allow-origin": "*",
'Content-Type': 'application/json;charset=UTF-8',
},
credentials: 'include'
}).then(res => res.json()).then(data => {
console.log(data);
getUserInfo();
})
}
const getUserInfo = () => {
fetch('http://api.nextu.top:5072/auth/userinfo', {
method: 'GET',
headers: {
"access-control-allow-origin": "*",
'Content-Type': 'application/json;charset=UTF-8',
},
credentials: 'include'
}).then(res => res.json()).then(data => console.log(data)).catch(err => console.log(err))
}
doLogin() working fine in each situation
getUserInfo() don't work when call from client and nestjs app hosted in online server
getUserInfo() has AuthGurd in nestjs
getUserInfo() working fine in postman
forbiden error :
I find a way to solve it:
changed from:
cookieSession({
keys: ['asdasd']
}),
);
to:
app.use(
cookieSession({
keys: ['asdasd'],
sameSite: 'none'
}),
);
and run client and server on https.
sameSite: 'none' just work on https mode
You should define on which domain the cookie is set, like so
app.use(cookieSession({
keys: ['asdasd'],
sameSite: 'strict',
domain:'.nextu.top'
}));
Note that the '.' is very important as it tell that cookie can be set on any subdomains of "nextu.top"
It work as expected on dev because your front and back are on the same domain "localhost", the only thing changing is the port, but on prod your front is "test.nextu.top" and back "api.nextu.top" which are not the same and cause your issue

How to fix CORS policy issue with get request?

please help me to solve CORS policy issue, it happens when I'm trying to make a get request to applications endpoint, and issue is only reproducible from http://localhost:8080/ on prod request works fine.
vue.config.js file
module.exports = {
devServer: {
proxy: 'https://spinstatus.zenoss.io/'
}
}
request method
const grabApps = async () => {
const res = await axios({
method: 'get',
url: `${spinnakerURL}/gate/applications`,
withCredentials: false,
crossdomain: true,
headers: {
'Access-Control-Allow-Origin': '*',
}
});
return res.data || []
}
error
headers from localhost request
headers from prod request
Change the devServer configuration in vue.config.js like this:
module.exports = {
devServer:
{
proxy:
{
'/gate':
{
target: 'https://spinstatus.zenoss.io',
changeOrigin: true,
onProxyReq: (proxyReq, req, res, options) =>
{
proxyReq.setHeader('Origin', 'https://spinstatus.zenoss.io');
}
}
}
}
};

Proxying an endpoint to avoid CORS issues

I am using an external api that doesn't allow client side POST request. I can make a POST request using node.js and I am getting my desired response on the server. I am stuck trying to figure out how to get the response from the server into my HTML file.
const https = require("https");
const data = JSON.stringify({
key: "value"
});
const options = {
hostname: "url",
port: 443,
path: "/path",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": data.length
}
};
const req = https.request(options, res => {
console.log(
`statusCode: ${res.statusCode} statusMessage: ${res.statusMessage}`
);
res.setEncoding("utf8");
res.on("data", chunk => {
console.log(chunk);
});
});
req.on("error", error => {
console.error(error);
});
req.write(data)
req.end();
This is my server.js file, I'm not sure what the next step is to get in a file.

missing authentification token for REST request elastic search

It's the first time I'm posting a question here: I'm creating a website in AngularJS for the front end and NodeJS for the back end. This website is supposed to give me information about my elastic search clusters, get some information from Elasticsearch index. I have tried to use Elasticsearch Javascript API to do my request but it doesn't work.
I'm using ElasticSearch 5.4
Here's an example of request :
var client = new elasticsearch.Client ({
host: 'https://noev02pe.fr:9200',
auth: 'user:password',
log: 'trace',
headers: {
'Authorization': 'Basic user:password',
}
});
export function connect() {
client.search({
index: 'metric-prod*',
q: 'kafka'
}
, function (error, response) {
console.log(response);
});
}
and the response on the console is :
{ error:
{ root_cause: [ [Object] ],
type: 'security_exception',
reason: 'missing authentication token for REST request [/metric-
prod*/_search?q=kafka]',
header: { 'WWW-Authenticate': 'Basic realm="security" charset="UTF-8"'
} },
status: 401 }
I also tried doing classic post request :
export function createUser(request,response,next){
var username = request.params.username;
var userData = querystring.stringify(request.body);
console.log(userData);
var options ={
hostname: 'noev02vr.fr',
port: 9200,
rejectUnauthorized: false,
path: "_xpack/security/user/"+username,
method:'POST',
headers: {
'Authorization': 'Basic ' + prodPass,
'Content-Type': 'application/json',
'Content-Length': userData.length
}
};
var post_req=http.request(options, function(res){
console.log('post user reussi');
res.on('data', function(data){
response.writeHead(res.statusCode);
response.write(data);
console.log(res.statusCode);
});
});
post_req.write(userData);
post_req.end();
}
and I get a 500 error.
Basic Authentication
const { Client } = require('#elastic/elasticsearch')
const client = new Client({
node: 'https://localhost:9200', //Replace with your URL.
auth: {
username: 'elastic',
password: '*****' //Replace with your password
}
})
Otherwise, you can provide your credentials in the node(s) URL
const { Client } = require('#elastic/elasticsearch')
const client = new Client({
node: 'https://username:password#localhost:9200'
})
If you have enable ssl then this are the config
const { Client } = require('#elastic/elasticsearch')
const client = new Client({
node: 'https://localhost:9200',
auth: {
username: 'elastic',
password: '*****'
},
ssl: {
ca: fs.readFileSync('./cacert.pem'),
rejectUnauthorized: false
}
})
You can get Your username and password refer this link
https://www.elastic.co/guide/en/cloud-enterprise/current/ece-password-reset-elastic.html

Node.js: Cannot do PROFIND with request module

I'm trying to access content of my WebDAV server in node (server OK, I can net use it). I'm using the request module:
path = url.join(this._options.rootUrl, path || "");
var data =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<propfind xmlns=\"DAV:\">" +
"<propname/>" +
"</propfind>";
var headers = {
"Content-Type": "text/xml",
"Depth": depth || 1
};
var req = request({
url: path,
data: data,
headers: headers,
method: "PROPFIND",
json: false,
encoding: "utf8",
auth: {
user: this._options.user,
password: this._options.password
}
});
req.on("response", ...);
req.on("error", ...);
The problem is I'm getting HTTP 405 instead of the result. I've tried bundled https module, same result.
Is it possible that Node.js cannot invoke costom verbs like PROPFIND?
UPDATE 1:
This is stated that node can do PROFIND. So my question is, how do you people do correct WebDAV PROPFIND client request in node/io.js by using request module? (Or anything that works for this purpose.)
PROPFIND or any other verb is supported just fine for outbound requests in node and iojs. There is either something else wrong with your request (wrong/bad headers or payload for example) or configuration on the server.
Example of PROPFIND working:
// client.js
require('http').request({
host: '127.0.0.1',
port: 8000,
method: 'PROPFIND'
}, function(res) {
res.resume();
}).end();
// server.js
require('http').createServer(function(req,res) {
// echoes "PROPFIND" to stdout
console.log(req.method);
res.writeHead(200, { 'Connection': 'close' });
res.end();
}).listen(8000);

Categories