Express Routing Params - javascript

I am looking to get this query from this url 'http://localhost:3000/#/quote/edit/?quote_number=1&line_number=1'
from this route in express
router.route('/quote/:quote_number&:line_number')
.get(checkAuthentication, (req, res) => {
let request = new sql.Request(pool)
let get_lines_query = `
select *
from quote_line
where quote_number = ${req.query.quote_number} and
line_number = ${req.query.line_number}`
but it is calling a different query from
route router.route('/quote/:quote_number')

Firstly, the URL you provided doesn't match the route. Your route is to /quote/number&line but your URL is of the form /quote/edit/?quote_number=number&line_number=line.
Secondly, parameters written as ?key=value&key2=value2 are called query parameters, and being special, standard forms of parameters, you don't need to bind them yourself. Express will parse them into the req.query object without you specifying the bindings. So all you need to do is change your route to /quote/edit and you're good.
On an unrelated note, please don't directly stick URL parameters into your SQL query. That's how you end up with SQL injection attacks. Depending on the SQL package you're using, there should be a way to use bound parameters in your queries instead.

Try updating your code to:
router.route('/quote/:quote_number/:line_number').get(function (req, res) {
let quote_numer = req.params.quote_number;
let line_number= req.params.line_number;
res.send(quote_numer + "" + line_number)
})

Related

Feature toggling using Expressjs middleware - frontend and backend

My current project is using Node for both frontend and backend and ExpressJS as the middleware.
I have a requirement where I need a feature toggling implementation to introduce some new features in my application. I am using a url parameter, e.g. &featureToggle=true to determine if the code of execution would be the new one or the existing.
Now I have parts in frontend and backend both which need to be changed based on the feature toggle. In the backend I can get the query object separately and extract the url param, similarly also in the frontend module.
Is there a way in which I can use Express to intercept the query param, set a variable value to either true or false based on the feature toggle, and which could be used across both the frontend and backend modules?
with express you can use req.query which gathers the query string sent in the request. You could pass it like this:
localhost:9000/path?&featureToggle=true
the ? is important it tells express that you are creating a query.
if you then place it into a variable:
const query = req.query
you would get the following output:
{ featureToggle: 'true' }
so as you can see it is returning an object.
you can check it like so:
if(req.query.featureToggle === 'true'){
runSomeCode();
};
or in your case if you want to run some kind of middleware:
router.get('/', (req, res, next) => {
if(req.query.featureToggle === 'true'){
return next(toggle)
}
};

Getting error 404 for put request (using express and node js) [duplicate]

I am trying to create two routes in my express app. One route, without a parameter will give me a list of choices, the other one with a parameter will give me the choice related to the id.
router.get('/api/choice', choice_controller.get_choices);
router.get('/api/choice/:id', choice_controller.get_choice);
When I go to .../api/choice/?id=1 the api returns the list of choices, and therefore follows the route without the param (/api/choice). How do I make sure that the router does not omit the parameter?
Thanks in advance.
UPDATE
It seems that it does not fire the /api/choice/:id route. If I remove the one without the param, it gives a 404 so. Could someone explain to me why /api/choice/?id=1 is not getting picked up by /api/choice/:id?
Basically, your declared routes are documented in the Express documentation.
The second route is resolved by a URL like /api/choice/hello where 'hello' is mapped into the req object object as:
router.get('/api/choice/:id', function (req, res) {
console.log("choice id is " + req.params.id);
});
What you are actually trying is mapping query parameters.
A URL like /api/choice/?id=1 is resolved by the first router you provided.
Query parameters are easy to get mapped against the request as:
router.get('/api/choice', function (req, res) {
console.log('id: ' + req.query.id);
//get the whole query as!
const queryStuff = JSON.stringify(req.query);
console.log(queryStuff)
});

Why is URL recognized by Express.js not like the usual URLs that we see?

Why is a URL that is recognizable to Express.js, not like the usual URLs we see?
For example:
Express.js will recognize this URL (http://localhost:3000/things/0) where id=0 if I make this GET request:
app.get('/things/:id', (req, res) => {
// Do somethihng
});
But this URL (http://localhost:3000/things/?id=0) which is more like the usual URLs we see won't work for the same GET request above.
So, "normal URLs" is apparently in the eye of the beholder as there are really just different styles, neither being any more normal than the other.
There are a couple ways to pass parameters in a URL.
#1 - You can embed it in the path of the URL
https://someserver/things/0
https://contacts.google.com/person/c3429579852656514228
This is referred to as a RESTFUL design. These URLs contain a noun and then an id that identifies which of those nouns the URL refers to.
#2 - You can put the variable part of the URL in a query parameter
For those same two URLs above, that could look like this:
https://someserver/things?id=0
https://contacts.google.com/person?id=c3429579852656514228
There are valid reasons for both designs depending upon circumstances and there are even cases where you combine the two (add optional query parameters to the restful API designs in option #1. Neither one is "normal" - they are different ways to design your URLs.
Express allows you to use either one. For restful parameters that are in the path of the URL, you use the :id syntax and you access the value in req.params.id:
app.get('/things/:id', (req, res) => {
console.log(req.params.id);
res.send(req.params.id);
});
For query parameters, you don't define them in the express route path. Instead, Express parses any query parameters that exist on any route and makes them available in req.query.
// expecting /things?id=789&sort=alpha
app.get('/things', (req, res) => {
console.log(req.query.id); // "789"
console.log(req.query.sort); // "alpha"
res.send(req.query.id);
});
Any query parameter that is present in the URL will be added to the req.query object.
Note that query parameters are often considered optional and thus you don't code them into your route definition. If you want to require a specific query parameter, then you have to check if it's there and, if not, then provide some error response or call next() to continue to routing to other request handlers.
FYI, there's another style that often uses client-side code to help build that page and puts URL arguments in a hash tag too, but I'll leave that for another day.
(http://localhost:3000/things/?id=0) which is more like the usual URLs
It's framework and it doesn't do what you and I think. It has set of rules.
Talking about best practices for RESTFUL API, design is that path params(/:id) are used to identify a specific resource or resources, while query parameters(?id) are used to sort/filter those resources. So, for /things/?id=0, We should use query parameters.
we see won't work for the same GET request above.
It will not work that way. In order to get query parameters use something like
app.get('/things', (req, res) => {
let id = req.query.id;
// here you can get id.
});
QUERY PARAMETERS:
How to get GET (query string) variables in Express.js on Node.js?
ABOUT URL: https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_URL

Can't get url Parameter inside controllerFunction node js

In my index.js I have given routing in such a manner.
app.use('/users/:id/transactions',transactionRoutes)
Inside transactionRoutes
router.get('/:txnHash',transactionController.getTransaction);
so request to '/users/:id/transactions/:txnHash' will come to the above route.
Inside transactionController
module.exports.getTransaction = (req,res) => {
let typeOfTransaction = req.query.type,
userId = req.params.id,
txnHash = req.params.txnHash;
}
Here I am able to access the txnHash parameter but the userId parameter shows undefined. I think it is because the :id part of the route is specified in the index.js. Is there any method to solve this problem without changing the routes.
API Request is
GET 'apiurl/users/42342234/transactions/234bh2428b354hjcs'
In your TransactionRoutes you need to add mergeParams which will preserve the req.params values.
var router = express.Router({mergeParams: true});
Before your,
router.get('/:txnHash',transactionController.getTransaction);
Hope this helps!

ExpressJS + JWT. What's the proper way to get auth data?

Let's jump to an example. I'll skip some parts like imports, exports.
I have a controller called controllers/book.js with one route:
router.get('/my-books', function(req, res) {
if(Auth.authenticated(req,res)) {
Book.getMyBooks(function(rows) {
response.operationSucceed(req, res, rows);
});
}
});
Then, in a model called models/book.js I have that function:
function getMyBooks(successCallback) {
db.query('SELECT * FROM book b WHERE b.id_user=?', [Auth.getLoggedUID()], function(rows) {
successCallback(rows);
});
}
My question is about Auth.getLoggedUID function.
Assuming that I have a JWT authentication and assuming that I have an UID in payload (is that even acceptable?), what's the best option to retrieve it? Is there any, EXCEPT passing the req every time to every function where I need auth data?
I may have a function execution inside a function, do I need to pass the req through both of them to get the user ID? Like this?:
function getBooks(req) {
getMyBooks(req);
getCriminalBooks(req);
getEvenOtherBooksByAuthor(req, authorId);
}
Honestly I wouldn't like that.
Maybe my whole concept is wrong and I should be doing things differently?
Can someone point me the right direction in scenarios like this?
You can pass UID in header and retrieve it inside your controller as:
var uid =req.header('UID');
Then pass this UID where ever you want there is no need to carryforward whole req object everywhere.
You can use a middleware function. Let's say that every request that hits your endpoints, will have a token which you should check and possibly decode it. After that, you can set the decoded content to the req object. So something like this:
app.use(function(req, res, next) {
// get the token from the request headers most likely.
// verify and decode the token
// set the decoded content to the request
var payload = ..
req.payload = payload;
});
After this you can access the payload in every single endpoint you have. So for example in some controller you can do:
app.get('/hey', function(req, res) {
var payload = req.payload;
});

Categories

Resources