I have an Express server, where my app is served from the app.get('*') route.
I'd like to have users with promo codes visit the site from a campaign URL like so: www.mysite.com/?code=123.
The problem is every browser request is routed to the favicon request, thus my req.url and req.query variables cannot be used to get the promo codes. Req.url is always /favicon.ico and req.query is always empty.
I did find the original URL is the request object's header, but this seems like a roundabout way of achieving my objective. The request object's original URL field also points to favicon.ico.
app.get('*', (req, res) => {
console.log(req.url);
console.log(req.query);
}
I'd like to keep my promo code solution as quick and dirty as possible for the time being, so I'm fine with URL parameters. Is there a simple solution to extract the original URL query parameters without diving into the headers?
EDIT: I'm now sharing my root request handler below. The favicon request is handled by the express-favicon middleware earlier in the code.
app.get('*', (req, res) => {
console.log("In get *");
console.log("Req.url: ",req.url);
console.log("Promo code: ",req.query.promo);
const context = {};
const app = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
const indexFile = path.resolve('./public/index.html');
fs.readFile(indexFile, 'utf8', (err, data) => {
if (err) {
console.error('Something went wrong:', err);
return res.status(500).send('Oops, better luck next time!');
}
return res.send(
data.replace('<div id="root"></div>', `<div id="root">${app}</div>`)
);
});
})
The problem is that I'm using React Router, which doesn't support query parameters:
https://reacttraining.com/react-router/web/example/query-parameters
To get aroud this, I'm using window.location.search on the client to get the promo code, then passing to the backend with an explicit promo handler.
You can accept dynamic value as part of the URL in express
api call ==> www.mysite.com/dynamic_promo_code
app.get('/:promo_code',(req,res)=>{
// req.params will be and object holding your dynamic promo_code
const promo = req.params.promo_code; // this will be your dynamic promo code
});
if you wish your promo code is opitional and don't want to be part of URL
api call ==> www.mysite.com?promocode=dynamic_promo_code
app.get('/',(req,res)=>{
//req.query is an object holding your optional parameter
const code = req.query.promocode; // this will be yor dynamic promo code
})
Related
I am creating a simple login form that (for now) will log you in as long as the username and password pass the client-side validation function. The form is shown here below (paraphrased a bit).
...
<form id="logonForm">
<input id="email">
<input id="password">
<button type="submit">Logon</button>
</form>
...
It should be noted that this form is being loaded at /login route (have a GET route set up there). On load of the page this form is assigned an onsubmit function as shown below.
...
document.getElementById("logonForm").onsubmit = loginUser;
As a note, loginUser is an imported function from another file. This function has been verified to work though as I am able to step through it when I submit the form. This function does a bunch but the main important parts are depicted below.
...
method = {
method: "POST",
body: loginDetails
};
fetch(url, method)
.then(result => result.json())
.then(result => sessionStorage.setItem("userToken", result[0].userToken))
.catch(error => alert(err.message))
This fetch queries a POST route also located at the /login route with the username and password sent over in FormData() encoding. When I run through this function, no error is thrown by the fetch (or prior/after the fetch) but result returns empty/null.
Investigating this from my server-side code I find that the "POST" route doesn't seem to be actioned even when the fetch is sent. In this following code "That" is never logged to the console but "This" is.
exports.logonUser = (app, formidable, fs, jwt) => {
console.log("This");
app.post('/login', (request, result, next) => {
console.log("That");
...
}
}
This function is called in my server.js file that is run to start the server as shown below.
const home = require('./api/routes/home.js');
const login = require('./api/routes/login.js');
app.use(express.static(path.join(__dirname, process.env.STATIC || 'public/')));
login.openRoute(app, path);
login.logonUser(app, formidable, fs, jwt);
app.use((request, result, next) => {
// This is "true" until I have tokens properly working
if (true) result.redirect('/login');
else next();
});
home.openRoute(app, path);
app.get('/', (request, result) => result.redirect('/home'));
app.listen(process.env.PORT || 3000, () => console.log("[SUCCESS][SERVER] Server is listening on port 3000"));
I have tried re-arranging the functions a bit, but this seems to be the order that gets the functionality as intended (other than the login not working). I have also tried taking out the part that automatically redirects users to /login in-case something funky was happening there, but no luck in that regard either. I am presuming there is something about my server.js code though that cause the POST route on /login to not action. Is there anything that you are able to see that might cause this behaviour? Thank you for all help.
I am making a front using Express. I have a table where each row has a link that makes a GET request, so that the back-end (done with node.js) returns a file corresponding to that row.
All links make the url GET request like "/documents/table/file".
What I intend to do is for my express server to be able to know which link of what row makes the GET request with the req field of it in order to be able to return the corresponding requested file.
The request is being handled in my express server as follows:
router.get('/documents/table/file', async (req, res) =>{
//Get which element made the get petition
});
As I said before, I intend to know what link from which row of the table performs a request using the req field.
You need to pass the information about the row/item that makes the GET request, that is a must.
Now with Express there are a couple of ways to do this: Express routing.
1. Defining route params: req.params
GET Request: /documents/table/file/345 (345 is the row identifier name or id etc)
At nodejs express end:
router.get("/documents/table/file/:id", (req, res) => {
/*request parameter with this kind of route sits in req.params*/
console.log(req.params);
const requestedId = req.params.id;
});
2. Sending as query string parameters: req.query
GET Request: /documents/table/file?id=345
At nodejs express end:
router.get("/documents/table/file/", (req, res) => {
/*request parameter with this kind of route sits in req.query*/
console.log(req.query);
const requestedId = req.query.id;
});
The short version is: you can't know this.
The way this is normally handled that if a request is needed for a specific item (or row in a table), you need to add some relevant information to the url that can identify it yourself.
So if it's a GET request for /foo/get-file, and every 'file' has some kind of unique id, you might want to change your url to /foo/get-file/123 or /foo/get-file?id=123
Do you want to access specific file using get command? If so, here's an answer - Express router - :id?.
More precisely, you write something like router.get('/documents/table/file/:id), and this :id is available in req.params object.
I'm attempting to store an object that my user clicks on in my server so that when the page changes, all the information from that object can be displayed fully in a profile page.
I'm unfamiliar with Angular $http but I've tried to write a call that will POST to the server, unfortunately when I scan through the req object in VScode I can't find where the object I sent is contained, so I can send it on to my function.
Controller function:
$scope.storeProfile = function(child){
$http.post('/storeTempProfile', child)
.then(function(response) {
window.location.href = 'DemoPage.html';
});
}
server.js:
app.post('/storeTempProfile', function (req, res) {
profileStorage.storeProfile(req);
});
does my app.post look right? And what property of req do I need to use the dot operator on to access my object? I can't seem to find the object data anywhere in req and that makes me thing there's something wrong with how I wrote app.post
It looks like you are using express. So in that case, you want to access the object on req.body, but this will require you use body-parser. The example on their homepage:
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// create application/json parser
var jsonParser = bodyParser.json()
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
if (!req.body) return res.sendStatus(400)
// create user in req.body
})
You will notice in this example that they pass the json parser into the route itself. This is only necessary if you want to have different parsers for different routes. Usually you just want to set it to all routes, which you can do by using app.use(bodyParser.json()).
I am working with node/express/passport/ looking at code that attempts to use a request like:
req._parsedUrl.pathname;
I cannot figure out where this variable is coming from. Is this a canonical variable name that is set in a common .js library? It doesn't seem exposed in any headers.
req._parsedUrl is created by the parseurl library which is used by Express' Router when handling an incoming request.
The Router doesn't actually intend to create req._parsedUrl. Instead parseurl creates the variable as a form of optimization through caching.
If you want to use req._parsedUrl.pathname do the following instead in order to ensure that your server doesn't crash if req._parsedUrl is missing:
var parseUrl = require('parseurl');
function yourMiddleware(req, res, next) {
var pathname = parseUrl(req).pathname;
// Do your thing with pathname
}
parseurl will return req._parsedUrl if it already exists or if not it does the parsing for the first time. Now you get the pathname in a save way while still not parsing the url more than once.
You can write a middleware to handle then set properties for req.
var myMiddleWare = function () {
return function (req, res, next) {
req._parsedUrl = 'SOME_THING';
next()
}
};
app.get('/', myMiddleWare, function (req, res) {
console.log(req._parsedUrl); // SOME_THING
res.end();
})
Express middleware document in here
I am using node and express for a web app.
I'd like to add a tag to my url when someone clicked on it but on the server side:
exports.route = function (state) {
return function (req, res) {
// here I'd like to add a line of code that will turn
// my url from 'http://path/index' to 'http://path/index?param=myParams'
res.render('index', {myParams});
};
};
How can I do this?
Many thanks
You could use a simple redirect:
if(!req.params.param) return res.redirect(req.url+'?param='+myParams);
If the querystring parameter is not defined or doesnt have the value you want, just redirect the user to the same url but with the parameter.