问题
I need to check the request headers on each page request. I thought the place to try this would be in the 'apostrophe-express' module. I've created my own module 'auth' that extends 'apostrophe-express':
module.exports = {
extend: 'apostrophe-express',
name: 'auth',
alias: 'auth',
absoluteUrl: function(req, res, next){
console.log(req);
}
};
But this isn't working. I'm getting an error 'apostrophe-templates\index.js" 597 req.browserCall('apos.pageReadywhenCalm($("body"));')'
Can you tell me where I should hook into each page request to run some custom checking/rule (e.g. if a certain cookie isnt present, then redirect the user to a different site)?
Thanks!
回答1:
I'm the principal architect of Apostrophe at P'unk Avenue.
You don't want to extend the apostrophe-express
module under a new name. That module provides the apos.app
singleton, so extending it under a new name just sets up apos.app
twice, leading to confusion and potential problems.
Intercepting every Express request
Instead, just leverage the middleware
option of the apostrophe-express
module. You can do that in app.js
:
var apos = require('apostrophe')({
modules: {
// Other module configuration here, then ...
'apostrophe-express': {
middleware: [
function(req, res, next) {
// Do whatever you like here
console.log(req.url);
// Let the request continue. You could also
// use res.redirect, res.send, etc. and
// bypass Apostrophe, in which case you
// should NOT call next
return next();
}
]
}
}
});
This is all you need, and you could use require
to pull the middleware function in from another file, reducing clutter in app.js
. However it's worth pointing out that you can move this code to a lib/modules/apostrophe-express/index.js
file in your project, to "implicitly subclass" that module. That opens the door to providing your own construct
property as well, which would permit you to override any of the methods of the module if you wanted to.
If you approach it this way, you don't need to touch app.js
at all:
// in lib/modules/apostrophe-express/index.js at project level
module.exports = {
middleware: [
function(req, res, next) {
console.log(req.url);
return next();
}
],
construct: function(self, options) {
// If you want, override methods of the module here
};
};
Intercepting the request just before page rendering
You specified "each page request," which I've interpreted to mean "each web request." But it's possible you specifically only want requests where Apostrophe is about to build and send a proper webpage.
For that, just add a pageBeforeSend
method to any of your own modules. Let's say our module is called cool-stuff
:
// in app.js
var apos = require('apostrophe')({
modules: {
// Other module configuration here, then ...
'cool-stuff': {}
}
});
// In lib/modules/cool-stuff/index.js
module.exports = {
construct: function(self, options) {
self.pageBeforeSend = function(req, callback) {
// Careful, there isn't always a page object; we could be
// rendering /login for instance
console.log(req.data.page && req.data.page._url);
return callback(null);
};
}
};
Apostrophe always calls pageBeforeSend
for every module that has such a method.
As seen above, take care not to assume req.data.page
is set, since there are a few cases where Apostrophe renders a full webpage as a response but there is no corresponding page object in Apostrophe's page tree.
Intercepting right after the page object is loaded
One more option: if pageBeforeSend
is too late in the process for you, for instance because you want widget loaders to see changes you've made to req
, use pageServe
instead...
// in app.js
var apos = require('apostrophe')({
modules: {
// Other module configuration here, then ...
'cool-stuff': {}
}
});
// lib/modules/cool-stuff/index.js
module.exports = {
construct: function(self, options) {
self.pageServe = function(req, callback) {
// Express request URL
console.log(req.url);
// URL of the best matching page available
console.log((req.data.page || req.data.bestPage)._url);
return callback(null);
};
}
};
Notice that I'm allowing for either req.data.page
or req.data.bestPage
to exist. If the URL doesn't exactly match a page, Apostrophe will set req.data.bestPage
to the page with the longest "path prefix" matching the URL. For instance, if the URL is /foo/bar and /foo exists but /foo/bar doesn't, req.data.bestPage
will be /foo
. Note that this means req.data.bestPage
will be the homepage in the worst case.
See the apostrophe-custom-pages
module for neat things you can do with this.
Hope this is helpful!
来源:https://stackoverflow.com/questions/39785274/check-headers-on-each-page-request