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
Related
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);
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!
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
});
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)
I have two different types of possible API class I can make.
The first one is:
http://api_url.com/api/v1/schools/countries/BR
and the second one is:
http://api_url.com/api/v1/schools/countries/BR?admin1=MA
My route in backend/routes/schools.js is:
router.get('/countries/:country', forward_get);
const forward_get = (req, res, next) => {
console.log(req);
const url = `${url}${req.originalUrl}`
getResponse(url, acToken, res);
}
How do I make it so that I am able to also make the second api call and get the appropriate parameters "admin1: MA". Ive gone through the whole req object and I don't seem to find them anywhere. So far I've been able to make the first api call without a problem.
This is the only route you need:
You access admin1 using req.query.admin1
and
You access country using req.params.country