Routes.js
The below code worked.
var upload= multer({ storage: storage})
app.post('/upload', [ upload.any(), function(req, res) {
console.log(req.body) // form fields
console.log(req.files) // form files
res.status(204).end()
}]);
However, I wanted to call a controller method as well which is located in my file uploadController.js
So I did this, down below.
app.post('/upload', controllers.uploadFiles.upload, [ upload.any(), function(req, res) {
console.log(req.body) // form fields
console.log(req.files) // form files
res.status(204).end()
}]);
However, what happened was that my controller was called but then uploading part failed, i.e the below part wasn't called.
console.log(req.body) // form fields
console.log(req.files) // form files
res.status(204).end()
In conclusion, either one of them (multer or controller) work, both of them don't.
What could be wrong with this?
UPDATE
Tried the below. Only controller gets called. No file uploading done.
app.post('/upload', controllers.dataUpload.upload, [ upload.any(), function(req, res, next) {
console.log(req.body) // form fields
console.log(req.files) // form files
next()
}]);
You haven't called next from the first controller. The execution ends after you call res.end(). If you want the execution to continue to the next route match, you must call next() on the first middle-ware.
You can read more about routing and middlewares in the guide: https://expressjs.com/en/guide/routing.html
Here are some quotes that might be relevant:
You need to call the next function so that the next controller is called:
More than one callback function can handle a route (make sure you specify the next object).
When you call methods on the res object, the execution is terminated and the next controller is ignored:
The methods on the response object (res) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.
Credits to #squgeim for helping me out with the conceptual part. According to his guidance, I figured out the issue. Below is the working code.
Routes.js
var uploadStorage = multer({ storage: storage})
app.post('/upload', controllers.uploadController.uploadFile, [uploadStorage.any(), function(req, res, next) {
console.log(req.body) // form fields
console.log(req.files) // form files
res.status(204).end()
}]);
uploadController.js
module.exports = {
uploadFile: (req, res, next) => {
//Do whatever you want over here.
next()
},
}
So basically, inside app.post argument #2, I call the controller, do whatever I want and then call next() to proceed forward to app.post arguments #3 which is calling multer and uploading file.
Related
I have this express.js code:
app.get('/', (req, res) => {
res.render('homePage', { title: 'Express' });
});
app.use((req, res) => {
console.log('use() is executed');
res.end();
});
If the request is handled by the get() method, use() is not supposed to execute. But I noticed that it still execute even though everything was fine and the page is rendered. Did I do something wrong or did I miss something? Thanks.
From Express Doc:
Link: http://expressjs.com/en/4x/api.html#app.use
app.use([path,] callback [, callback...])
Mounts the specified middleware function or functions at the specified path: the middleware function is executed when the base of the requested path matches the path.
app.use() register the function as middleware, and you didn't specify the path. That's why it will run every time when any route is called.
The placement of the middlewares will change the execution order. However, they don't change the fact that the middleware will be executed as, well middlewares, which will be executed before the actual functions with in the routes.
Hi I'm trying to make it so that when a user opens a page it won't open until the data from the server is successfully retrieved so that it won't appear after 0.5s or so after the user enters.
To do this I read that I need to use BeforeRouteEnter but I'm having trouble finding information on how to properly use this, especially with waiting for my REST API to complete its request.
Here's the method I want to wait to complete before routing to my new component:
async getThread() {
const response = await postsService.fetchOneThread({
id: this.blockId,
topic: this.topicId,
thread: this.postId
});
this.thread = response.data;
}
so once this.thread = response.data only then do I want the page to display.
An important thing to note is that I am also passing through URL parameters to get the data which is the topic/black/post ID.
Here is my getUrlParam method also
url() {
let x = this.$route.params.topic.split('-');
this.topicId = x[0];
let y = this.$route.params.id.split('-');
this.blockId = y[0];
let post = this.$route.params.thread.split('-');
this.postId = post[1];
this.getThread();
}
Thanks
You need to move getThread inside beforeRouteEnter
beforeRouteEnter: (to, from, next) => {
postsService.fetchOneThread({
id: this.blockId,
topic: this.topicId,
thread: this.postId
}).then( response => {
//store the data somewhere accessible
next()
})
},
A few notes:
I don't think beforeRouteEnter can be async, so I'm using then to get the response
the component is not yet ready, so you can't access it yet, you need to save the information some other place so it can be read by the component. I'd suggest using Vuex for this.
If you decide to use Vuex than you need to add a mutation and call it from the promise's callback.
store.commit('ADD_THREAD', response.data)
Here are my routes:
app.get('/signUp', routes.signUp);
app.post('/signUp' , routes.signUp);
Here is my separate file for routes.
exports.signUp = function(req, res) {
res.render('signUp');
};
The second block of code is behaviour I want in response to a get request.
How do I respond to a post request? I have already tied up the signUp function with behaviour that responds to get. Do I bundle up the post behaviour in the same function and render the sign up page again? Suppose I simply want to render the view, I don't want the post behaviour to execute in that case so it would be strange to bundle those together.
I believe the express router module should resolve this for you.
route file -
var express = require('express');
var router = express.Router();
router.route("/")
.get(function (req, res) {
res.render('signUp');
})
.post(function (req, res) {
//do something else
})
module.exports = router
index.js/app.js/server.js/whatever you call it.
//..
signUp = require("./routes/signup.js"); //or wherever this is
//...
app.use("/signUp", signUp);
//..
I am using expressjs to implement api calls for my app. Much of the time I don't want to send back extra data in the body however expressjs sends the http status text in the response if you don't specify a body.
For res.send(200); outputs OK in the body, res.send(400); outputs Not Found and so on.
The problem is that my UI is expecting well formatted JSON or an empty body, and the bare strings break this convention. The work around I've found for now is to send res.send(200,{}); to send an empty object, but that's a pain in the butt to do that for every api call.
Is there any way to get around express returning this bare text on an empty response?
Without modifying the express library itself, you can create a middleware function that extends the functionality of res.send.
You can modify res.send so an empty string is added to its arguments when invoked only with a status code. This will prevent the name of the status code from being sent.
app.use(function(req, res, next) {
var send = res.send;
res.send = function() {
if (arguments.length == 1 && typeof arguments[0] == 'number') {
arguments[arguments.length++] = '';
}
return send.apply(res, arguments);
};
next();
});
app.get('/good', function(req, res) {
res.send(200);
});
app.get('/not-found', function(req, res) {
res.send(404);
});
I'm using a expressjs 4.x to build a simple api on top of mongodb.
The api needs to serve a few sets of data:
/api/v1/datatype1
/api/v1/datatype2
For each data type, I have CRUD operations (post, get, put, delete).
The api requests would look like this:
POST /api/v1/datatype1
GET /api/v1/datatype1:_id
PUT /api/v1/datatype1:_id
DELETE /api/v1/datatype1:_id
If I create a router params like this:
dataType1ApiRouter.param("entity_id", function (req, res, next, id) {
//async db fetch here by id, then call next with fetched data
//or error if faild request/not found entity.
//let's say req.dataEntity = dataEtity; next();
} );
If I create a route like this:
dataType1ApiRouter.route("/datatype1")
.get(":entity_id", function (req, res, next) {
//expcet req.dataEntity to be fetched by the param filter.
})
.post(function(req, res, next) {
//just create an new dataType1 entity.
});
I am getting a syntax error. The route .get and .post (and other methods like those) expect just one parameter, resulting in an error:
Route.get() requires callback functions but got a [object String]
Is there a way to actually group all the "/datatype1" requests under one url declaration instead of repeating the method("datatype1:entity_id") for each method that requires the ID expect for the post method?
There isn't a clean way to do this with Router.route(), but you might consider doing this with another Router instead of a Route there. Then, you could just mount that sub-router.
Basic example, modifying the code you provided:
var mainRouter = express.Router(),
subrouter = express.Router();
subrouter.param("entity_id", function (req, res, next, id) {
// param handler attached to subrouter
});
subrouter.post('/', function(req, res, next) {
// post handler attached to base mount-point
});
subrouter.get("/:entity_id", function (req, res, next) {
// get handler attached to base mount-point/<id>
});
// here we mount the sub-router at /datatype1 on the other router
mainRouter.use('/datatype1', subrouter);
Note that this requires adding a '/' to the URL, so instead of /api/v1/datatype1[someidhere] it would be /api/v1/datatype1/someidhere