Node js Error: Protocol "https:" not supported. Expected "http:" - javascript

I am using IBM Bluemix to make a web service for a school project.
My project needs to request a JSON from an API, so I can use the data it provides. I use the http get method for a data set, and I am not sure if it is working properly.
When I run my code, I get the message:
Error: Protocol "https:" not supported. Expected "http:"
What is causing it and how can I solve it?
Here is my .js file:
// Hello.
//
// This is JSHint, a tool that helps to detect errors and potential
// problems in your JavaScript code.
//
// To start, simply enter some JavaScript anywhere on this page. Your
// report will appear on the right side.
//
// Additionally, you can toggle specific options in the Configure
// menu.
function main() {
return 'Hello, World!';
}
main();/*eslint-env node*/
//------------------------------------------------------------------------------
// node.js starter application for Bluemix
//------------------------------------------------------------------------------
// HTTP request - duas alternativas
var http = require('http');
var request = require('request');
// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require('cfenv');
//chama o express, que abre o servidor
var express = require('express');
// create a new express server
var app = express();
// serve the files out of ./public as our main files
app.use(express.static(__dirname + '/public'));
// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();
// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {
// print a message when the server starts listening
console.log("server starting on " + appEnv.url);
});
app.get('/home1', function (req,res) {
http.get('http://developers.agenciaideias.com.br/cotacoes/json', function (res2) {
var body = '';
res2.on('data', function (chunk) {
body += chunk;
});
res2.on('end', function () {
var json = JSON.parse(body);
var CotacaoDolar = json["dolar"]["cotacao"];
var VariacaoDolar = json["dolar"]["variacao"];
var CotacaoEuro = json["euro"]["cotacao"];
var VariacaoEuro = json["euro"]["variacao"];
var Atualizacao = json["atualizacao"];
obj=req.query;
DolarUsuario=obj['dolar'];
RealUsuario=Number(obj['dolar'])*CotacaoDolar;
EuroUsuario=obj['euro'];
RealUsuario2=Number(obj['euro'])*CotacaoEuro;
Oi=1*VariacaoDolar;
Oi2=1*VariacaoEuro;
if (VariacaoDolar<0) {
recomend= "Recomenda-se, portanto, comprar dólares.";
}
else if (VariacaoDolar=0){
recomend="";
}
else {
recomend="Recomenda-se, portanto, vender dólares.";
}
if (VariacaoEuro<0) {
recomend2= "Recomenda-se, portanto, comprar euros.";
}
else if (VariacaoEuro=0){
recomend2="";
}
else {
recomend2="Recomenda-se,portanto, vender euros.";
}
res.render('cotacao_response.jade', {
'CotacaoDolar':CotacaoDolar,
'VariacaoDolar':VariacaoDolar,
'Atualizacao':Atualizacao,
'RealUsuario':RealUsuario,
'DolarUsuario':DolarUsuario,
'CotacaoEuro':CotacaoEuro,
'VariacaoEuro':VariacaoEuro,
'RealUsuario2':RealUsuario2,
'recomend':recomend,
'recomend2':recomend2,
'Oi':Oi,
'Oi2':Oi2
});
app.get('/home2', function (req,res) {
http.get('https://www.quandl.com/api/v3/datasets/BCB/432.json?api_key=d1HxqKq2esLRKDmZSHR2', function (res3) {
var body = '';
res3.on('data', function (chunk) {
body += chunk;
});
res3.on('end', function () {
var x=json.dataset.data[0][1];
console.log("My JSON is "+x); });
});
});
});
});
});
Here is a print of the error screen I get:

When you want to request an https resource, you need to use https.get, not http.get.
https://nodejs.org/api/https.html

As a side note to anyone looking for a solution from Google... make sure you are not using an http.Agent with an https request or you will get this error.

The reason for this error is that you are trying to call a HTTPS URI from a HTTP client. The ideal solution would have been for a generic module to figure out the URI protocol and take the decision to use HTTPS or HTTP internally.
The way I overcame this problem is by using the switching logic on my own.
Below is some code which did the switching for me.
var http = require('http');
var https = require('https');
// Setting http to be the default client to retrieve the URI.
var url = new URL("https://www.google.com")
var client = http; /* default client */
// You can use url.protocol as well
/*if (url.toString().indexOf("https") === 0){
client = https;
}*/
/* Enhancement : using the URL.protocol parameter
* the URL object , provides a parameter url.protocol that gives you
* the protocol value ( determined by the protocol ID before
* the ":" in the url.
* This makes it easier to determine the protocol, and to support other
* protocols like ftp , file etc)
*/
client = (url.protocol == "https:") ? https : client;
// Now the client is loaded with the correct Client to retrieve the URI.
var req = client.get(url, function(res){
// Do what you wanted to do with the response 'res'.
console.log(res);
});

Not sure why, but the issue for me happened after updating node to version 17, i was previously using version 12.
In my setup, i have node-fetch using HttpsProxyAgent as an agent in the options object.
options['agent'] = new HttpsProxyAgent(`http://${process.env.AWS_HTTP_PROXY}`)
response = await fetch(url, options)
Switching back to node 12 fixed the problem:
nvm use 12.18.3

I got this error while deploying the code.
INFO error=> TypeError [ERR_INVALID_PROTOCOL]: Protocol "https:" not supported. Expected "http:"
at new NodeError (node:internal/errors:372:5)
To fix this issue, I have updated the "https-proxy-agent" package version to "^5.0.0"
Now the error was gone and it's working for me.

Related

Trying to capture Client IP Address for already running server in localhost, but node.js conflicts with existing server

I am trying to capture client ipaddress for traffic visiting my localhost:8080. I am using the following modules and the node.js application looks like this
var connect = require('connect');
var http = require('http');
var net = require('net');
var express = require('express');
var app = express();
var app = connect();
// require request-ip and register it as middleware
var requestIp = require('request-ip');
// you can override which attirbute the ip will be set on by
// passing in an options object with an attributeName
app.use(requestIp.mw({ attributeName : 'myCustomAttributeName' }))
// respond to all requests
app.use(function(req, res) {
// use our custom attributeName that we registered in the middleware
var ip = req.myCustomAttributeName;
console.log(ip);
fs.appendFile('iplist.csv', ip, 'utf8', function (err) {
if (err) {
console.log('Some error occured - file either not saved or corrupted file saved');
} else{
console.log('It\'s saved!');
}
});
// https://nodejs.org/api/net.html#net_net_isip_input
// var ipType = net.isIP(ip); // returns 0 for invalid, 4 for IPv4, and 6 for IPv6
// res.end('IP address is ' + ip + ' and is of type IPv' + ipType + '\n');
});
//create node.js http server and listen on port
app.listen(8080);
Is there any way I can listen to the already existing server without creating my own, hence avoiding the conflict of two servers fighting for the same port. I am new to node.js. Any help will be great. Thank you!

(crypto.js) TypeError: Data must be string or buffer

I am currently using crypto.js module to hash things. It was working for a while then I started getting this error:
Here is the foundation of my server:
process.stdout.write('\033c'); // Clear the console on startup
var
express = require("express"),
app = express(),
http = require("http").Server(app),
io = require("socket.io")(http),
path = require("path"),
colorworks = require("colorworks").create(),
fs = require("fs"),
crypto = require("crypto");
function md5(msg){
return crypto.createHash("md5").update(msg).digest("base64");
}
function sha256(msg) {
return crypto.createHash("sha256").update(msg).digest("base64");
}
http.listen(443, function(){
// Create the http server so it can be accessed via 127.0.0.1:443 in a web browser.
console.log("NJ project webserver is running on port 443.");
// Notify the console that the server is up and running
});
app.use(express.static(__dirname + "/public"));
app.get("/", function(request, response){
response.sendFile(__dirname + "/public/index.html");
});
I am aware that these functions are creating the problem:
function md5(msg){
return crypto.createHash("md5").update(msg).digest("base64");
}
function sha256(msg) {
return crypto.createHash("sha256").update(msg).digest("base64");
}
The problem being, if these functions don't work (which they don't anymore), roughly 200 lines of code will go to waste.
This error is triggered by attempting to hash a variable that does not exist:
function md5(msg){
return crypto.createHash("md5").update(msg).digest("base64");
}
function sha256(msg) {
return crypto.createHash("sha256").update(msg).digest("base64");
}
md5(non_existent); // This variable does not exist.
What kind of data are you trying to hash ? Where does it come from ?
I would check the value of msg first then I would try :
crypto.createHash('md5').update(msg.toString()).digest('hex');
You could also use these packages instead:
https://www.npmjs.com/package/md5
https://www.npmjs.com/package/js-sha256

HTTP Proxy: Reject half-processed request

I have HTTP Proxy based on Node.js which transforms response body on fly in stream fashion. For instance, my proxy works like nginx, which compresses (using libz for gzipping) response body.
But I have open question: What if error occures on upstream connection during the data exchange. How to notify client about en error, when response have already been sent and transmitting body is in progress. Complexity of error determination on client side based on fact that Content-Length is absent in response due to source and transformed data mismatch.
To clarify some details I added a simple piece of code:
var express = require("express");
var http = require("http");
var url = require('url');
var webApp = express();
var httpServer = webApp.listen(8080, function () {
console.log("server started on ", 8080, " port");
});
webApp.get("*", function(req, res) {
var targetRequest = http.get(req.originalUrl, function (upstreamResponse) {
if (upstreamResponse.statusCode != 200) {
res.status(500).send("Internal Server Error");
return;
}
upstreamResponse.on("data", function (chunk) {
/// transform chunk and send it to the client
res.write(chunk);
});
upstreamResponse.on("end", function () {
res.end();
});
/// upstream connection error occured
upstreamResponse.on("error", function (error) {
/// How to properly notify client
/// about error ????
/// ????
});
});
});
Actually, the only one way to notify clients about some issues is just to drop downstream connections.

HTTP Proxy using node connect

Note: My question may be very similar to this question, but the solution is not working for me.
My problem is the same as the original poster. I need to access an external resource, and I need to proxy to it to get around cross domain security restrictions. I had also referenced this sample blog post: http://nthloop.com/blog/local-dev-with-nodejs-proxy/
The proxy is working to load external resources (anything containing 'cgi' in the url). But with this code, I am no logner able to hit local (static) files with the connect module. Times out, no error messages, etc...
I am posting the full code of my server.js file:
var httpProxy = require('http-proxy');
var connect = require('connect');
var endpoint = {
host: '11.0.0.120',
port: 8081
};
var proxy = new httpProxy.RoutingProxy();
var app = connect()
.use(function(req, res) {
if (req.url.indexOf('cgi') >= 0) {
proxy.proxyRequest(req, res, endpoint);
} else {connect.static(__dirname)};
})
.use(connect.static(__dirname))
.listen(8182);
This question's solution seemed to state that I needed to include an else condition. It doesn't wok without or without one.
Thanks for any help!
You can use next() to let request flow to the next middleware -
var app = connect()
.use(function(req, res, next) {
if (req.url.indexOf('cgi') >= 0) {
proxy.proxyRequest(req, res, endpoint);
} else {
next();
)};
})
.use(connect.static(__dirname))
.listen(8182);
Oops, got it working just by swapping the use(connect...) function to the first call. Don't know why this worked or if it is the best approach. Also, didn't need the else statement.
If someone can give a better explanation I can accept their answer. Here's my working code:
var httpProxy = require('http-proxy');
var connect = require('connect');
var endpoint = {
host: '11.0.0.120',
port: 8081
};
var proxy = new httpProxy.RoutingProxy();
var app = connect()
.use(connect.static(__dirname))
.use(function(req, res) {
if (req.url.indexOf('cgi') >= 0) {
proxy.proxyRequest(req, res, endpoint);
}
})
.listen(8182);

How to create a streaming API with NodeJS

How would you go to create a streaming API with Node? just like the Twitter streaming API.
What I want to do ultimately is get the first update from the FriendFeed api, and stream when a new one becomes available (if the id is different), and later on expose it as a web service so I can use it with WebSockets on my website :).
So far I have this:
var sys = require('sys'),
http = require('http');
var ff = http.createClient(80, 'friendfeed-api.com');
var request = ff.request('GET', '/v2/feed/igorgue?num=1',
{'host': 'friendfeed-api.com'});
request.addListener('response', function (response) {
response.setEncoding('utf8'); // this is *very* important!
response.addListener('data', function (chunk) {
var data = JSON.parse(chunk);
sys.puts(data.entries[0].body);
});
});
request.end();
Which only gets the data from FriendFeed, creating the Http server with node is easy but it can't return a stream (or I haven't yet found out how).
You would want to set up a system that keeps track of incoming requests and stores their response objects. Then when it's time to stream a new event from FriendFeed, iterate through their response objects and responses[i].write('something') out to them.
Check out LearnBoost's Socket.IO-Node, you may even just be able to use that project as your framework and not have to code it yourself.
From the Socket.IO-Node example app (for chat):
io.listen(server, {
onClientConnect: function(client){
client.send(json({ buffer: buffer }));
client.broadcast(json({ announcement: client.sessionId + ' connected' }));
},
onClientDisconnect: function(client){
client.broadcast(json({ announcement: client.sessionId + ' disconnected' }));
},
onClientMessage: function(message, client){
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.broadcast(json(msg));
}
});

Categories