richardschneider / express-mung Goto Github PK
View Code? Open in Web Editor NEWExpress response transformations (or make until no good)
License: MIT License
Express response transformations (or make until no good)
License: MIT License
I'm quite new on express so I'm not sure if this is a no-sense, but is it possible to modify content served using express.static
? I've tried the following code and inspect
is never being called.
var app = require('express')();
const mung = require('express-mung');
function inspect (json, req, res) {
console.log('>>>>>');
json.inspected_by = 'me'
}
app.use(mung.json(inspect));
app.use('/static', express.static('static'));
app.listen(3000, function(){
console.log('mung listening on *:3000');
});
there are couple fixes not in the 0.5.1 release. please release a new version to npm
I'm using express-mung in a common library, this for my express backend, but other functions of the library I use in the frontend. In the backend everything works correctly relating to express-mung but in the frontend an error occurs when trying to execute the unit tests:
PhantomJS 2.1.1 (Linux 0.0.0) ERROR
SyntaxError: Use of reserved word 'let' in strict mode
at webpack:///~/express-mung/index.js:3:0 <- src/test.ts:174140
PhantomJS 2.1.1 (Linux 0.0.0) ERROR
SyntaxError: Use of reserved word 'let' in strict mode
at webpack:///~/express-mung/index.js:3:0 <- src/test.ts:174140
any suggestions?
If I move the express-mung as last middleware the app can respond but the function 'redact' (as the name from usage example) which I want to modify the response is not called.
I used express generator to scaffold my app.
Code below the app does not respond.
app.use(mung);
// routes, users and api are express router
app.use('/', routes);
app.use('/users', users);
app.use('/api', api);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
Code below the app can respond but function 'redact' is not called
// routes, users and api are express router
app.use('/', routes);
app.use('/users', users);
app.use('/api', api);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.use(mung);
module.exports = app;
I would like to save api request together with the corresponding response data.
I understand that is not possible with mung at this moment. Am I correct?
What would be a possible workaround?
Their is nothing mentioned regarding onError function how to use this, i been trying to include this as
app.use(mung.onError(function(err, req, res){}));
but i keep recieving this error
TypeError: Cannot read property 'status' of undefined
Which is defined in
express-mung/index.js
I would like to use this plugin for non-JSON data. I'd like to just post-process data as a string, if possible.
@richardschneider Is it possible that mung.write
isn't called in some scenarios? My code looked something like this example below, but I wasn't getting the expected behavior. It was part of a larger project, but I'm working on a reduced complexity app to reproduce the issue.
// kinda like...
var express = require('express')
var mung = require('express-mung')
var app = express()
app.use(express.static('public'))
app.use(mung.write(function (chunk,encoding,req,res) {
console.log('hello world')
return 'gotcha'
})
I would expect the body of the response to be gotcha
, but it's not.
I would expect to see hello world
in the console, but I don't.
I have a use case for a mung.writeJson
function which overrides the res.write
function only when the response type application/json
.
For example, apollo-server sends graphQL responses via res.write
, after setting the Content-Type
and Content-Length
headers. You can take a look at the specific source code here. If this happens, mung.json
is never called even though the response is a json object.
Thoughts on this? I have a simple working implementation, I have opened a pull request (#14). Let me know what you think ๐
It seems like res.status()
and mung.json()
don't play well together.
I'm fairly new to express in general so I may be doing something wrong here, but I would have expected to be able to do something like:
//untested pseudo-code, I can cook up a better example that
//fully illustrates the problem if necessary.
function getSomething(req, res) {
//hack because there seems to be no way to get status from `res` in express:
res.locals.statusCode = 404;
//set status code to 404 and send json
res.status(404).json({message: 'Resource not found'});
}
function addMeta(body, req, res) {
//this function *never* gets called when calling `res.status()` as in the `getSomething()` function.
body.statusCode = res.locals.statusCode;
}
app.use(mung.json(addMeta));
app.get('/something', getSomething);
Once res.status()
is called, the addMeta method never gets called it seems.
What I'm really trying to do here is provide a way for my api to slap on extra meta data at the end of the json response with the http status code for clients that may not be able to receive non-200 http status codes. It would be great to be able to, from the addMeta
function in my example, make a call like res.getStatus()
and check the status code that has been set by res.status()
in the previous middleware or route or whatever.
I was using express-mung today and found that it was lacking something I needed. I wanted to gather timings for some calls and I ended up having to write a function to grab a begin-time and use it as normal middleware before the call. Then, I used an express-mung function to grab the begin-time from the request object and insert call time and elapsed time as an attribute of the body.
So I was thinking, how about adding the ability to provide a function which can interact with request & response when the user calls use() and then doing the normal stuff. Basically, if a caller provides another function, call it here:
Lines 21 to 23 in af48316
That way, I could refactor my code eventually to be something like:
app.use(mung.json(startTimer, {}, stopTimer)
So, is there any interest in this? I'd be willing to contribute the changes if so.
ReferenceError: Cannot access 'args' before initialization
Line 141 in 6efded3
This variable is used before it is defined.
Im trying to make a call to: mung.json(audit, { mungError:true}); The audit function is never executing in my PROD environment. Works perfectly fine locally and in my DEV environment. Both local, DEV and PROD are AWS EC2 instances.
Here is a bigger code example:
const mung = require('express-mung');
module.exports = function(app) {
function audit(json, req, res) {
//do stuff
console.log("inside audit");
}
console.log("module.exports is executing");
return mung.json(audit, { mungError:true});
}
I have more stuff in audit... but figure the console should just write out. When I start the server I see "module.exports is executing" so I know it is making it in there (that shows up in all environments). The odd part is that it works locally and in DEV but not in PROD. Could it possibly be some odd EC2 setting? Just seems to odd that this call doesnt work in Prod!
If a json munger returns a scalar value instead of a object, i.e. its really a map-reduce, then we should honour it by setting content-type
to text/plain
and sending the value as text (toString).
Many JSON implementations allow a scalar value. But the fact is that the JSON spec only allows an object
or an array
.
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
When a response is sent during a mung
then it should be aborted.
This can easily happen when the mung
detects an exception and immediately sends the error message.
All mung
operations should abort when res.headersSent
is true
.
I noticed that mung.onError
always assumes the Accept content type is application/json, and sends a json
response. I guess we can modify this on our own, but I was just sharing the bug find.
The mung functions are not invoked when the response is in error (res.statusCode >= 400
). This is by design, because the functions would not receive an expected response to work on.
However, @hk0i has raised a valid use case #6 to mung the error response.
To maintain backwards compatibility, an optional options
argument is added to the various methods. This allows munging of an error, such as mung.json(fn, { mungError: true })
.
When using mung.write
chrome throws an ERR_CONTENT_LENGTH_MISMATCH 200 (OK)
if the new content is different (I guess smaller) in size (reported here).
The simple solution I found is to
const changedChunk = JSON.stringify(bodyJson);
res.set('Content-Length', changedChunk.length);
but I guess mung.write
could do the same behind the scenes.
BTW thanks for this library, its a life saver!
PS: For reference the code is
expressInstance.use(
mung.write((chunk, encoding, req, res) => {
if (req.graphqlLodash_transform) {
const bodyJson = JSON.parse(chunk);
bodyJson.data = req.graphqlLodash_transform(bodyJson.data);
const changedChunk = JSON.stringify(bodyJson);
res.set('Content-Length', changedChunk.length);
return changedChunk;
} // else return unmodified
}),
);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.