Express js repeat route journey with context - javascript

I've been sitting with this for few days already and I'm brain dead from this and can't figure the best way to approach this.
What I would like to achieve is to be able to repeat the route journey with new context data on the start. So for rxample:
app.get('/test', testGet);
app.post('/test', testPost);
having those two routes I would like:
GO through testGet handler (fetch necessary data and present ui for Form)
Gather Form data and submit it for the testPost handler
Process data from form on testPost and generate appropirate new payload
Redirect again to the testGet handler with new payload data from testPost if journey not successful
How I would pass that new data to the testGet on redirection? Can't figure the best way.
Redirect doesn't accept any payload. Redirecting with query params is kinda way to go but it appends the url string with query string to the user which I would like not to be present to the user. And that data would not be a simple string but an object containing few arrays and properties

Look at this
const handleRequest = (req, res, next) => {
const view = 'myView.jsx';
let myData = {};
...do the common job
if (req.method === 'GET') {
return res.render(view, data)
}
/* here you are in the post method */
data = /* modify your data with the req.body */
return res.render(view, data)
};
app.get('/test', handleRequest);
app.post('/test', handleRequest);

Related

How to create an express update route with multiple parameters

I want to update an attribute within a JSON object using fetch PUT. I've created a put function taking in 2 URL parameters
app.put('/trustRoutes/:id/:item', (req, res){
I am able to update the data with a single parameter but since I only want to change one value inside that object, calling put will replace the whole object with my new body.
below is what I've tried.
app.put('/trustRoutes/:id/:item', (req, res) => {
readFile(data => {
const userId = req.params['id/item'];
// have also tried const userId = req.params.id.item
data[userId] = req.body;
//write data back to file
I looked around at other examples but couldn't find any that were updating data instead of GET. If there is one I missed please let me know.
PUT requests are great for completely overwriting a resource, and is idempotent. This answer does a good job explaining idempotency. For updating a resource partially, a PATCH request is a better choice.
app.patch('/trustRoutes/:id/:item', (req, res) => {
readFile(data => {
data[userId] = req.params[id];
data[item] = req.params[item];
// A get request for this resource would now show both of the updated values
// Write file

Koa server-- How to pass data in the server between middlewares so I can pass it to the front end

In my server, I have the following set up to grab the current logged-in user data:
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
createShopifyAuth({
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
const client = new Shopify.Clients.Rest(shop, accessToken);
const data = await client.get({
path: 'users/current',
});
I am correctly getting the data but I would like to pass it to the front end.
I've tried storing the data in a global variable, I've tried storing the data in app.context and I've tried storing the data in ctx.state.
My idea is that I'd be able to grab the data and place it in the following so that I can make a fetch request to this /user endpoint:
router.get('/user', (ctx,next) => {
next();
console.log('check for ctx.state: ', ctx.state);
})
At the end of the day, I need access to the shop and accessToken from the Auth function which is why I'd need to pass the data instead of making the data request in the router.get function.
I haven't worked with Koa before so any help would be greatly appreciated. Thank you!
I figured this out in case this may be helpful to anyone else:
within the server.use function, I grabbed the data and stored it as the following:
server.context.db = data;
This context allows you to pass it around to other middlewares throughout the app. I then assigned ctx.body = ctx.db.body
in my router so that I could use a fetch request to hit that endpoint

How to share information between Express middleware and endpoints?

Lots of middleware comes with factories, that takes an options object. Among the options is usually a function that needs to provide some necessary information to the middleware. As an example, take a look at express-preconditions:
app.use(preconditions({
stateAsync: async (req) => { // Fetch the date the resource was last modified. }}
});
This is a neat pattern, but I find it gets complicated when the same information is needed in multiple places. For instance, let's say I've got a database table that contains both the information about the resource that the response is supposed to contain, and the last modified date. In other words, the same information is needed in both the middleware and the endpoint itself. I end up with code similar to this:
//The middleware
app.use(preconditions({
stateAsync: async (req) => {
const data = await fetchFromDb(req.param("id"));
return {
lastModified: data.lastModified
};
})
//The endpoint
app.use("path", (req, res, next) => {
const data = await fetchFromDb(req.param("id"));
res.send(data);
});
I'm hitting the database twice just because I need the same info in different places. I could off course just fetch it once, or store it somewhere on the request object. But that feels a bit like a hack. Another solution would be to have some kind of caching mechanism in fetchFromDb, but that feels a bit overcomplicated.
In my experience, this is a quite common problem when building stuff with Express. What is the recommended way to deal with situations like this?
You can pass data between middlewares with res.locals:
app.get('/yourEndPoint', (req, res, next) => {
const data = // fetch your datas;
res.locals.lastModified = data.lastModified;
next();
}, (req, res) => {
const lastModified = res.locals.lastModified;
// do whatever you need to do
});

Going back to file where redirect call was made in Express

Currently, in a function inside of an Express app I am working on, I would like to make a redirect after gathering some data, have that redirect finish, return that data and then continue from where I left off.
For example:
> res.redirect('my/path' + someVariable);
> Goes through various routes, and web pages, gathering data
> Come back to the point after the initial redirect, with new data
> Do some checks with previous and new data, continue on
Is this something that is common? Are there easy ways of accomplishing this? I can clarify further if need be.
Thanks!
Pass data as querystring around. See example below (run locally and navigate to localhost:4000/path0 to see the effect).
const express = require('express')
const app = express()
app.get('/path0', (req, res, next) => {
if (!req.query.value) { // no data yet
res.redirect('/path1?redirect=/path0') // go to another path to fetch data
} else {
res.write(`<h1>Value is: ${req.query.value}</h1>`)
res.end()
}
})
app.get('/path1', (req, res, next) => {
let value = Math.random(10) // assume this is the data we want
let redirectPath = req.query.redirect || '/path0'
res.redirect(`/path0?value=${value}`) // redirect back, this time pass data as part of querystring
})
app.listen(4000)
Another possible way to pass data back is through Set-Cookie after first redirect, instead of directly passing the data into querystring of second redirect. (should be working in most modern browser even given 302, see this)

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