Express Set Custom Parameter Query Starter - express

I'm using express to interact with discord's oauth2 api.
When I request a user oauth token the server responds with a url like:
http://localhost:3000/index#token_type=Bearer&access_token=tkn&expires_in=int
I'm trying to extract the parameters after the # as with discords api parameters start with # unlike others which start with a ?
Because it doesn't start with a question mark I am unable to use the req.params.x property.
I thought, "No big deal, ill just get the url and extract it myself" but every single url accessor in express removes string after #. This includes req.url and req.originalUrl which both return the file path.
So how can I get url parameters started by hashtags instead of question marks?
Or How can I get the full url with content after hashtags

I was able to solve this problem by setting a custom query parser. Code snippet below.
const app = express();
app.set('query parser', (query) => {
return query.split('&').map(item => {
const [key, value] = item.split('=');
return {
key,
value
}
});
});
app.get('/', (req, res) => {
console.log(req.originalUrl); // Full URL starting with file path
})

Related

How does redirecting from a post method to get method work?

The server doesn't recognize any get request except for the post method after executing some queries in the mongodb.
The express middleware takes the post method and after interacting with the database and using the res.redirect() to get to other get methods, the server doesn't recognize the request at all. I tried using res.all(). This showed that the request was seen but no action was taken.
var express = require('express');
var router = express.Router();
var Product = require('../models/product');
router.get('/', function(req, res, next) {`//homepage
res.render("index");
}
router.post('/add',function(req,res next){
//Product model
var prod = new Product({
//data here
});
prod.save(function(err,res2){
if(err){
console.log(err);
return res.redirect('/error');
}
else{
mongoose.disconnect();
console.log("Complete1");
return res.redirect('/');
console.log ("Complete2);
}
});
}
After I get to the post method it should redirect to the homepage
The problem may not be with the backend, but with the frontend. If you are using AJAX to send your POST request, it is specifically designed to not change your url.
Use window.location.href after AJAX's request has completed (in the .done()) to update the URL with the desired path, or use JQuery: $('body').replaceWith(data) when you receive the HTML back from the reques

Is there any way to add extra parameters in sails middleware?

We have a sails application behind azure authentication which passes a header with email address.
I need to use this email address as a param in my all controllers.
I am trying to add below in my sails http.js middleware. But I am not receiving the param as expected in controller.
aadAppendUser: function (req, res, next) { //Azure Active Directory append User Email
sails.log("Requested :: ", req.method, req.url);
const emailHeader = 'x-ms-client-principal-name';
req.param.userMail = req.headers[emailHeader];
sails.log("userMail :: ", req.param.userMail);
// sails.log('All Params', req.allParams());
return next();
}
I also added it to the order in http.js file.
Please suggest me if there is any other way to achieve this.
req.params is the key on which parameter exists, and req.param is the function to access these parameters.
please try setting on req.params.
Moreover req.param is now deprecated
req.params: http://expressjs.com/en/api.html#req.params
req.param: http://expressjs.com/en/api.html#req.param

Using node-spotify-web-api to grant user access and fetch data

So I'm new to using OAuth and I honestly got quite lost trying to make this work. I looked up the documentation for Spotify's Authorization code and also found a wrapper for node which I used.
I want to be able to log in a user through spotify and from there do API calls to the Spotify API.
Looking through an example, I ended up with this code for the /callback route which is hit after the user is granted access and Spotify Accounts services redirects you there:
app.get('/callback', (req, res) => {
const { code, state } = req.query;
const storedState = req.cookies ? req.cookies[STATE_KEY] : null;
if (state === null || state !== storedState) {
res.redirect('/#/error/state mismatch');
} else {
res.clearCookie(STATE_KEY);
spotifyApi.authorizationCodeGrant(code).then(data => {
const { expires_in, access_token, refresh_token } = data.body;
// Set the access token on the API object to use it in later calls
spotifyApi.setAccessToken(access_token);
spotifyApi.setRefreshToken(refresh_token);
// use the access token to access the Spotify Web API
spotifyApi.getMe().then(({ body }) => {
console.log(body);
});
res.redirect(`/#/user/${access_token}/${refresh_token}`);
}).catch(err => {
res.redirect('/#/error/invalid token');
});
}
});
So above, at the end of the request the token is passed to the browser to make requests from there: res.redirect('/#/user/${access_token}/${refresh_token}');
What if insted of redirecting there, I want to redirect a user to a form where he can search for artists. Do I need so somehow pass the token around the params at all time? How would I redirect a user there? I tried simply rendering a new page and passing params there but it didn't work.
you could store the tokens in a variety of places, including the query parameters or cookies - but I'd recommend using localstorage. When your frontend loads the /#/user/${access_token}/${refresh_token} route, you could grab the values and store them in localstorage (e.g. localstorage.set('accessToken', accessToken)) and retrieve them later when you need to make calls to the API.

Mixing Wildcards and Parameters in Express

I have web content generated by Minecraft Overviewer in:
/home/mc/backups/servername/latest/overviewer
I have a very simple server with express/nodejs. Here is my app.js:
var express = require('express');
var app = express();
//----------------------------------------------------------------------------+
// Each server's root points to the latest overviewer page |
//----------------------------------------------------------------------------+
app.get('/minecraft/:server/*', function(req, res) {
console.log('HELLO?');
res.send('Finally some luck!');
/*
var
server = req.params.server,
file = req.params[0] ? req.params[0] : 'index.html',
dir = '../backups/' + server + '/latest/overviewer';
res.sendFile(file, { root: dir });
*/
});
app.use(express.static('www'));
app.listen(80, function () {
console.log('Web server listening on port 80');
});
I included a little more code than what is running so you can see my intent in case this is an xy kind of problem. I'm wanting to route static files, but I don't think I can use express.static because I want the URL to be mapped a little differently than my file structure (and based on a server name).
So what's the problem with my simple server? When I try and navigate to mysite.com/minecraft/isopre I see a white page saying Cannot GET /minecraft/isopre. If I remove the * from the end of the string I'm routing on line 7 I see Finally some luck!. But I want the star there so I can map mysite.com/minecraft/isopre to index.html or mysite.com/minecraft/isopre/overviewer.js.
So what's the right way to go about doing this?
In order to perform desirable operation i suggest you to use ? symbol for regular expression:
app.get('/minecraft/:server/:file?', function(req, res, next) {
if('undefined' != typeof req.params.file && req.params.file) {
var file = req.params.file;
}
if('undefined' != typeof req.params.server && req.params.server) {
var server = req.params.server;
}
});
In this case :file become optional and node.js won't fail your entire application if wildcard is absent.
Hereby, if req.params.file variable is undefined you could serve index.html file.

Using Node JS to proxy http and modify response

I'm trying to write a front end to an API service with Node JS.
I'd like to be able to have a user point their browser at my node server and make a request. The node script would modify the input to the request, call the api service, then modify the output and pass back to the user.
I like the solution here (with Express JS and node-http-proxy) as it passes the cookies and headers directly from the user through my site to the api server.
proxy request in node.js / express
I see how to modify the input to the request, but i can't figure out how to modify the response. Any suggestions?
transformer-proxy could be useful here. I'm the author of this plugin and I'm answering here because I found this page when looking for the same question and wasn't satisfied with harmon as I don't want to manipulate HTML.
Maybe someone else is looking for this and finds it useful.
Harmon is designed to plug into node-http-proxy https://github.com/No9/harmon
It uses trumpet and so is stream based to work around any buffering problems.
It uses an element and attribute selector to enable manipulation of a response.
This can be used to modify output response.
See here: https://github.com/nodejitsu/node-http-proxy/issues/382#issuecomment-14895039
http-proxy-interceptor is a middleware I wrote for this very purpose. It allows you to modify the http response using one or more transform streams. There are tons of stream-based packages available (like trumpet, which harmon uses), and by using streams you can avoid buffering the entire response.
var httpProxy = require('http-proxy');
var modifyResponse = require('http-proxy-response-rewrite');
var proxy = httpProxy.createServer({
target:'target server IP here',
});
proxy.listen(8001);
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong. And we are reporting a custom error message.');
});
proxy.on('proxyRes', function (proxyRes, req, res) {
modifyResponse(res, proxyRes.headers['content-encoding'], function (body) {
if (body && (body.indexOf("<process-order-response>")!= -1)) {
var beforeTag = "</receipt-text>"; //tag after which u can add data to
// response
var beforeTagBody = body.substring(0,(body.indexOf(beforeTag) + beforeTag.length));
var requiredXml = " <ga-loyalty-rewards>\n"+
"<previousBalance>0</previousBalance>\n"+
"<availableBalance>0</availableBalance>\n"+
"<accuruedAmount>0</accuruedAmount>\n"+
"<redeemedAmount>0</redeemedAmount>\n"+
"</ga-loyalty-rewards>";
var afterTagBody = body.substring(body.indexOf(beforeTag)+ beforeTag.length)+
var res = [];
res.push(beforeTagBody, requiredXml, afterTagBody);
console.log(res.join(""));
return res.join("");
}
return body;
});
});