Node.js SSL error - no ciphers available - javascript

I was able to upload files to dropbox using request.js module. I was trying to upload file using pure Node.js https.request() and request.write(). As dropbox needs https connection, I am using https.request(). But I am receiving error while using them(second code):
When secureProtocol is SSLv2_method:
Problem with request: 3074844416:error:140650B5:SSL routines:CLIENT_HELLO:no ciphers available:../deps/openssl/openssl/ssl/s2_clnt.c:562:
After I change secureProtocol to SSLv3_method I receive error:
Problem with request: write EPROTO 3074537216:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:../deps/openssl/openssl/ssl/s3_pkt.c:348:
I was not able to install kerberos. Could this be the problem ?
Here are my code:
Using request.js module:
At last few lines I am piping the readable stream to request.put().
var crypto = require('crypto'),
express = require('express'),
request = require('request'),
url = require('url'),
cookieParser = require('cookie-parser'),
fs = require('fs');
app = express();
app.use(cookieParser());
var APP_KEY = 'opmdwo6kpnyswfp';
var APP_SECRET = 'an6vl11lc9rp51e';
function generateCSRFToken() {
return crypto.randomBytes(18).toString('base64')
.replace(/\//g,'-').replace(/\+/g,'_');
}
function generateRedirectURI(req) {
return url.format({
protocol: req.protocol,
host: req.headers.host,
pathname: app.path() + '/callback'
});
}
function getFileSize(fileName) {
var stats = fs.statSync(fileName);
var fileSizeInBytes = stats["size"];
var fileSizeInMegaBytes = fileSizeInBytes / 1000000.0;
return fileSizeInBytes;
}
app.get('/', function(req, res, next) {
var csrfToken = generateCSRFToken();
res.cookie('csrf',csrfToken);
res.redirect(url.format({
protocol: 'https',
hostname: 'www.dropbox.com',
pathname: '1/oauth2/authorize',
query: {
client_id: APP_KEY,
response_type: 'code',
state: csrfToken,
redirect_uri: generateRedirectURI(req)
}
}));
});
app.get('/callback', function(req, res) {
if(req.query.error) {
return res.send('ERROR ' + req.query.error + ': ' +
req.query.error_description);
}
if(req.query.state !== req.cookies.csrf) {
return res.status(401).send('CSRF token mismatch, possible' +
'cross-site request forgery attempt.'
);
}
request.post('https://api.dropbox.com/1/oauth2/token', {
form: {
code: req.query.code,
grant_type: 'authorization_code',
redirect_uri: generateRedirectURI(req)
},
auth: {
user: APP_KEY,
pass: APP_SECRET
}
}, function(error, response, body) {
var data = JSON.parse(body);
if(data.error)
return res.send('ERROR: ' + data.error);
var token = data.access_token;
var fileName = "aai_success.pdf";
var path = encodeURI("https://content.dropboxapi.com/1/files_put/auto/" + fileName);
fs.createReadStream(fileName).pipe(request.put(path, {
headers: { Authorization: 'Bearer ' + token },
'Content-Length': getFileSize(fileName)
}, function(error, response, body) {
console.log(response);
}));
});
});
app.listen(3000, function() {
console.log('Application is running on port 3000');
});
Using Node.js https.request()
var crypto = require('crypto'),
https = require('https');
express = require('express'),
request = require('request'),
url = require('url'),
cookieParser = require('cookie-parser'),
fs = require('fs'),
app = express();
app.use(cookieParser());
var APP_KEY = 'opmdwo6kpnyswfp';
var APP_SECRET = 'an6vl11lc9rp51e';
function generateCSRFToken() {
return crypto.randomBytes(18).toString('base64')
.replace(/\//g,'-').replace(/\+/g,'_');
}
function generateRedirectURI(req) {
return url.format({
protocol: req.protocol,
host: req.headers.host,
pathname: app.path() + '/callback'
});
}
function getFileSize(fileName) {
var stats = fs.statSync(fileName);
var fileSizeInBytes = stats["size"];
var fileSizeInMegaBytes = fileSizeInBytes / 1000000.0;
return fileSizeInBytes;
}
app.get('/', function(req, res, next) {
var csrfToken = generateCSRFToken();
res.cookie('csrf',csrfToken);
res.redirect(url.format({
protocol: 'https',
hostname: 'www.dropbox.com',
pathname: '1/oauth2/authorize',
query: {
client_id: APP_KEY,
response_type: 'code',
state: csrfToken,
redirect_uri: generateRedirectURI(req)
}
}));
});
app.get('/callback', function(req, res) {
if(req.query.error) {
return res.send('ERROR ' + req.query.error + ': ' +
req.query.error_description);
}
if(req.query.state !== req.cookies.csrf) {
return res.status(401).send('CSRF token mismatch, possible' +
'cross-site request forgery attempt.'
);
}
request.post('https://api.dropbox.com/1/oauth2/token', {
form: {
code: req.query.code,
grant_type: 'authorization_code',
redirect_uri: generateRedirectURI(req)
},
auth: {
user: APP_KEY,
pass: APP_SECRET
}
}, function(error, response, body) {
var data = JSON.parse(body);
if(data.error)
return res.send('ERROR: ' + data.error);
var token = data.access_token;
console.log("Access token: " + token);
var fileName = "aai_success.pdf";
var options = {
hostname: 'content.dropboxapi.com',
port: 80,
path: '/1/files_put/auto/test.txt',
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'multipart/form-data',
'Content-Length': 2,
'Transfer-Encoding': 'chunked'
},
strictSSL: false,
secureProtocol: 'SSLv3_method'
};
var rqst = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
});
});
rqst.write('AB');
rqst.end();
rqst.on('error', function(e) {
console.log('Problem with request: ' + e.message);
});
/*
var bts = 0;
fs.createReadStream(fileName).on('data', function(chunk) {
console.log("Got %d bytes from disk: ", chunk.length);
bts += bts + chunk.length;
var bytesSent = rqst.write(chunk);
console.log('Bytes sent: ' + bytesSent);
});
if(bts == 240519)
rqst.end();
*/
});
});
app.listen(3000, function() {
console.log('Application is running on port 3000');
});

You need to obtain a server certificate. You can self sign one for development using openssl (assuming you're on Linux) or you can obtain temporarily free ones. You also have the option to buy one from a certificate authority. Once you obtain a certificate look at the node.js docs under HTTPS or look at TLS (recommended) you can use their examples verbatim to setup SSL. https://nodejs.org/api/https.html
https://nodejs.org/api/tls.html

Solved the problem.
Change the port number to 443 and
remove the Content-Type header in options variable.
Didn't need to use strictSSL and secureProtocol
Didn't need to use SSL certificate.

Related

Cannot set headers after they are sent to the client, how do I stop Express from setting headers that have already been set?

I'm using Express, Node, and EJS to fetch data from Spotify Web API. Without EJS, I'm able to send a request from browser and fetch data no problem. With EJS, code crashes with code: 'ERR_HTTP_HEADERS_SENT' once I send a request in the browser. I'm lost on how to stop express from sending headers that have already been set.
const express = require("express");
const request = require("request");
const app = express();
const secret = require("./secret");
const redirect_uri = "http://localhost:8888/callback";
const client_id = secret.client_id;
const client_secret = secret.client_secret;
const querystring = require("querystring");
let state = "abc123";
let scope =
"user-read-private user-read-email user-read-recently-played user-top-read";
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.set("view engine", "ejs");
// Request User Authorization
app.get("/login", function (req, res) {
return res.redirect(
"https://accounts.spotify.com/authorize?" +
querystring.stringify({
response_type: "code",
client_id: client_id,
scope: scope,
redirect_uri: redirect_uri,
state: state,
})
);
});
// Request Access Token
app.get("/callback", function (req, res) {
let code = req.query.code || null;
state = req.query.state || null;
if (state === null) {
return res.redirect(
"/#" +
querystring.stringify({
error: "state_mismatch",
})
);
} else {
authOptions = {
url: "https://accounts.spotify.com/api/token",
form: {
code: code,
redirect_uri: redirect_uri,
grant_type: "authorization_code",
},
headers: {
Authorization:
"Basic " +
new Buffer(client_id + ":" + client_secret).toString("base64"),
},
json: true,
};
}
// User Recently Played Tracks
request.post(authOptions, function (error, response, body) {
if (!error && response.statusCode === 200) {
let access_token = body.access_token;
let refresh_token = body.refresh_token;
let options = {
url: "https://api.spotify.com/v1/me/player/recently-played",
headers: { Authorization: "Bearer " + access_token },
json: true,
};
// use the access token to access the Spotify Web API
request.get(options, function (error, response, body) {
let items = body.items;
// Track Names
for (let i = 0; i < items.length; i++) {
let trackName = items[i].track.name;
console.log(trackName);
}
// Artist Names
for (let i = 0; i < items.length; i++) {
let artistName = items[i].track.artists[0].name;
console.log(artistName);
}
});
// we can also pass the token to the browser to make requests from there
return res.redirect(
"/#" +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token,
})
);
} else {
return res.redirect(
"/#" +
querystring.stringify({
error: "invalid_token",
})
);
}
});
return res.render("index");
});
// Refresh Token
app.get("/refresh_token", function (req, res) {
let refresh_token = req.query.refresh_token;
let authOptions = {
url: "https://accounts.spotify.com/api/token",
headers: {
Authorization:
"Basic " +
new Buffer(client_id + ":" + client_secret).toString("base64"),
},
form: {
grant_type: "refresh_token",
refresh_token: refresh_token,
},
json: true,
};
request.post(authOptions, function (error, response, body) {
if (!error && response.statusCode === 200) {
let access_token = body.access_token;
return res.send({
access_token: access_token,
});
}
});
});
app.listen(8888, () => console.log("Server started on port 8888"));

Can't access /playlists using express and app.get

I'm trying to access the app.get('/playlists') but it keeps coming up a 404 status code error and the browser is displaying cannot GET /playlists
I'm unsure what I'm doing tthat is isn't accessible here's the code:
var express = require('express'); // Express web server framework
var stateKey = 'spotify_auth_state';
var app = express();
app.use(express.static(__dirname + '/public'))
.use(cors())
.use(cookieParser());
app.get('/callback', function(req, res) {
// your application requests refresh and access tokens
// after checking the state parameter
var code = req.query.code || null;
var state = req.query.state || null;
var storedState = req.cookies ? req.cookies[stateKey] : null;
if (state === null || state !== storedState) {
res.redirect('/#' +
querystring.stringify({
error: 'state_mismatch'
}));
} else {
res.clearCookie(stateKey);
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: redirect_uri,
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer(client_id + ':' +
client_secret).toString('base64'))
},
json: true
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token,
refresh_token = body.refresh_token;
var options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + access_token },
json: true
};
// use the access token to access the Spotify Web API
request.get(options, function(error, response, body) {
console.log(body);
});
// we can also pass the token to the browser to make requests from there
res.redirect('/#' +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token
}));
} else {
res.redirect('/#' +
querystring.stringify({
error: 'invalid_token'
}));
}
});
}
});
app.get('/refresh_token', function(req, res) {
// requesting access token from refresh token
var refresh_token = req.query.refresh_token;
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
headers: { 'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) },
form: {
grant_type: 'refresh_token',
refresh_token: refresh_token
},
json: true
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token;
res.send({
'access_token': access_token
});
}
});
app.get('/playlists', (req, res) => {
console.log(request.url);
response.send('Hello, /');
});
});
console.log('Listening on 8888');
app.listen(8888);
I can't figure out why the route won't work
Your /playlists endpoint is declared inside of the /refresh_token endpoint. Moving it outside of that should work.

Spotify authorization code grant: Bad Request

I am trying to create a website that uses the Spotify APIs and I am stuck trying to get the authorization code flow to work. Below is the code that I am using.
app.get('/login', function(req, res) {
var scope = 'user-read-private';
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: clientId,
scope: scope,
redirect_uri: redirectUri,
state: state
}));
});
app.get('/callback', function(req, res) {
res.status(200);
var code = req.query.code;
console.log('\ncode:', code, '\n');
spotify.authorizationCodeGrant(code).then(
function(data) {
console.log('The access token expires in ' + data.body['expires_in']);
console.log('The access token is ' + data.body['access_token']);
spotify.setAccessToken(data.body['access_token']);
spotify.setRefreshToken(data.body['refresh_token']);
},
function(err) {
console.log('Could not login!', err);
}
);
res.redirect('/');
});
The problem that I am having is that when it gets to the authorizeCodeGrant call it just fails and gives me a 400 bad request error and I am not sure why because I know that I am getting a code from Spotify, the code just does not seem to work.
var path = require('path');
var express = require('express');
var request = require('request');
var exphbs = require('express-handlebars');
var querystring = require('querystring');
var url = require('url');
var Spotify = require('spotify-web-api-node');
var keys = require('./keys');
var scopes = ['playlist-modify-private', 'user-read-private'],
redirectUri = 'http://localhost:3000/callback',
clientId = 'client_id',
clientSecret = 'client_secret',
state = 'some-state-of-my-choice';
var spotify = new Spotify({
redirectUri: redirectUri,
clientId: clientId,
redirectUri: redirectUri
});
var results = [];
var login = 1;//keeps track if logged into spotify
var tokenExpiration;
var app = express();
var port = process.env.PORT || 3000;
app.engine('handlebars', exphbs({ defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.get('/', function(req, res, next){
res.status(200);
res.render('searchPage', {
login: login,
results: results
});
});
app.get('/login', function(req, res) {
var scope = 'user-read-private';
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: clientId,
scope: scope,
redirect_uri: redirectUri,
state: state
}));
});
app.get('/callback', function(req, res) {
var code = req.query.code;
console.log('\ncode:', code, '\n');
spotify.authorizationCodeGrant(code).then(
function(data) {
console.log('The access token expires in ' + data.body['expires_in']);
console.log('The access token is ' + data.body['access_token']);
spotify.setAccessToken(data.body['access_token']);
spotify.setRefreshToken(data.body['refresh_token']);
tokenExpiration = new Data().getTime()/1000 + data.body['expires_in'];
login = 0;
},
function(err) {
console.log('Could not login!', err);
}
);
if(login == 0){
res.redirect('/#' +
querystring.stringify({
access_token: spotify.getAccessToken(),
refresh_token: spotify.getRefreshToken()
}));
}else{
res.redirect('/');
}
});
var numberOfTimesUpdated = 0;
setInterval(function() {
if(++numberOfTimesUpdated > 5 && login == 0) {
clearInterval(this);
spotify.refreshAccessToken().then(
function(data) {
tokenExpiration = new Data().getTime()/1000 + data.body['expires_in'];
spotify.setAccessToken(data.body['access_token']);
},
function(err) {
console.log('Could not refresh the token!', err.message);
}
);
}
}, 1000);
app.post('/search/:title', function(req, res) {
var search = req.params.title.toLowerCase();//req.body.search;
console.log('search', search);
resutls = [];
spotify.searchTracks(search, function(err, data) {
if(err) {
console.error('something went wrong...');
return;
}
console.log('I got' + search.body.tracks.total + 'results!');
search.body.tracks.items.forEach(function(track){
results.push({
artist: track.artist[0].name,
song: track.name,
preview: track.external_urls.sp,
album: track.album.name
});
res.render('searchPage', {
login: login,
results: results
});
});
});
});
app.use(express.static('public'));
app.listen(port, function(err){
console.log("== Server is listening on port", port);
});
Above is the full code for the server.

How to send a POST request from node.js Express?

Could someone show me the simplest way to send a post request from node.js Express, including how to pass and retrieve some data? I am expecting something similar to cURL in PHP.
var request = require('request');
function updateClient(postData){
var clientServerOptions = {
uri: 'http://'+clientHost+''+clientContext,
body: JSON.stringify(postData),
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
}
request(clientServerOptions, function (error, response) {
console.log(error,response.body);
return;
});
}
For this to work, your server must be something like:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())
var port = 9000;
app.post('/sample/put/data', function(req, res) {
console.log('receiving data ...');
console.log('body is ',req.body);
res.send(req.body);
});
// start the server
app.listen(port);
console.log('Server started! At http://localhost:' + port);
As described here for a post request :
var http = require('http');
var options = {
host: 'www.host.com',
path: '/',
port: '80',
method: 'POST'
};
callback = function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
}
var req = http.request(options, callback);
//This is the data we are posting, it needs to be a string or a buffer
req.write("data");
req.end();
you can try like this:
var request = require('request');
request.post({ headers: {'content-type' : 'application/json'}
, url: <your URL>, body: <req_body in json> }
, function(error, response, body){
console.log(body);
});
in your server side the code looks like:
var request = require('request');
app.post('/add', function(req, res){
console.log(req.body);
request.post(
{
url:'http://localhost:6001/add',
json: {
unit_name:req.body.unit_name,
unit_price:req.body.unit_price
},
headers: {
'Content-Type': 'application/json'
}
},
function(error, response, body){
// console.log(error);
// console.log(response);
console.log(body);
res.send(body);
});
// res.send("body");
});
in receiving end server code looks like:
app.post('/add', function(req, res){
console.log('received request')
console.log(req.body);
let adunit = new AdUnit(req.body);
adunit.save()
.then(game => {
res.status(200).json({'adUnit':'AdUnit is added successfully'})
})
.catch(err => {
res.status(400).send('unable to save to database');
})
});
Schema is just two properties unit_name and unit_price.
I use superagent, which is simliar to jQuery.
Here is the docs
And the demo like:
var sa = require('superagent');
sa.post('url')
.send({key: value})
.end(function(err, res) {
//TODO
});
Try this. It works for me.
const express = require("express");
const app = express();
app.use(express.json());
const PORT = 3000;
const jobTypes = [
{ id: 1, type: "Interior" },
{ id: 2, type: "Etterior" },
{ id: 3, type: "Roof" },
{ id: 4, type: "Renovations" },
{ id: 5, type: "Roof" },
];
app.post("/api/jobtypes", (req, res) => {
const jobtype = { id: jobTypes.length + 1, type: req.body.type };
jobTypes.push(jobtype);
res.send(jobtype);
});
app.listen(PORT, console.log(`Listening on port ${PORT}....`));

how to send the response to browser fromm http.request in node.js?

I am using the sample code from nodejs.org and trying to send the response to the browser .
var http = require("http");
var port = 8001;
http.createServer().listen(port);
var options = {
host: "xxx",
port: 5984,
//path: "/_all_dbs",
path: "xxxxx",
method: "GET"
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
var buffer = "";
buffer += chunk;
var parsedData = JSON.parse(buffer);
console.log(parsedData);
console.log("Name of the contact "+parsedData.name);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write("hello");
req.end();
But req.write("hello") just does not output the string to the browser ?
Is this not the right way ? can someone also tell me how to output the response to the html in views folder so that i can populate the response to the static html .
Try this:
var http = require('http');
var options = {
host: "127.0.0.1",
port: 5984,
path: "/_all_dbs",
method: "GET"
};
http.createServer(function(req,res){
var rq = http.request(options, function(rs) {
rs.on('data', function (chunk) {
res.write(chunk);
});
rs.on('end', function () {
res.end();
});
});
rq.end();
}).listen(8001);
Edit:
This node script saves the output to a file:
var http = require('http');
var fs=require('fs');
var options = {
host: "127.0.0.1",
port: 5984,
path: "/_all_dbs",
method: "GET"
};
var buffer="";
var rq = http.request(options, function(rs) {
rs.on('data', function (chunk) {
buffer+=chunk;
});
rs.on('end', function () {
fs.writeFile('/path/to/viewsfolder/your.html',buffer,function(err){
if (err) throw err;
console.log('It\'s saved!');
});
});
});
rq.end();

Categories