Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move req / res prototype extension to a separate repo #2432

Open
Fishrock123 opened this issue Nov 7, 2014 · 12 comments
Open

Move req / res prototype extension to a separate repo #2432

Fishrock123 opened this issue Nov 7, 2014 · 12 comments
Assignees
Milestone

Comments

@Fishrock123
Copy link
Contributor

@dougwilson should be added to #2237

@dougwilson dougwilson mentioned this issue Nov 7, 2014
39 tasks
@dougwilson dougwilson added this to the 5.0 milestone Nov 7, 2014
@Fishrock123 Fishrock123 self-assigned this Nov 21, 2014
@Fishrock123
Copy link
Contributor Author

Extraction of the logic is almost done, but we also need to decide on where to put the properties.

The suggestion was to bundle these into "packs".

List of req / res prototype properties in express 4.10.6:

// Request
[ 'header',
  'get',
  'accepts',
  'acceptsEncodings',
  'acceptsEncoding',
  'acceptsCharsets',
  'acceptsCharset',
  'acceptsLanguages',
  'acceptsLanguage',
  'range',
  'param',
  'is',
  'protocol',
  'secure',
  'ip',
  'ips',
  'subdomains',
  'path',
  'hostname',
  'host',
  'fresh',
  'stale',
  'xhr' ]

// Response
[ 'status',
  'links',
  'send',
  'json',
  'jsonp',
  'sendStatus',
  'sendFile',
  'sendfile',
  'download',
  'type',
  'contentType',
  'format',
  'attachment',
  'header',
  'set',
  'get',
  'clearCookie',
  'cookie',
  'location',
  'redirect',
  'vary',
  'render' ]

@Fishrock123
Copy link
Contributor Author

The one very easy one is that render() should come with the views abstraction. (but it depends on send() still...)

@NickStefan
Copy link

As long as the req / res prototypes are being moved to separate repos, I wanted to ask if there was a compelling reason to keep these as middleware processes rather than just directly modifying the http streams before ever making a server?

  • It would cut down on the amount of __proto__ replacement logic that has been brought up in issues before.
  • It would thin out the expressInit 'mandatory' middleware. It could be similar to some of the changes in the query middleware(?)
  • The req & res objects, to be extended onto http, could still be exposed off of express (and be modular etc).

Stupid simple example:
example.js

var _ = require('lodash');
var http = require('http');
var res = require('response');

_.extend(http.ServerResponse.prototype, res);

var server = http.createServer(function(request,response){
  response.render('example',{'hello':'hello world'});
});

server.listen(8000);

I just tested a quick and dirty implementation with express by

  • removing req.__proto__ = app.request; and res.__proto__ = app.response;, in lib/middleware/init.js
  • adding the prototypes directly onto http, in application.js.
app.listen = function(){

  // replace the servers response stream and request stream
  http.IncomingMessage.prototype = this.request;
  http.ServerResponse.prototype = this.response;

  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};

Is there a compelling reason to keep req.__proto__ = app.request; and res.__proto__ = app.response; as a middleware process? I've always thought the current middleware implementation was possibly slower, uses deprecated __proto__, and has more mental overhead to understand/modify.

@dougwilson
Copy link
Contributor

No, we won't be removing the use of __proto__. The reason I these cannot be globals. Users should be able to have an Express server in the same process as a plain http server and the plain http server should not have any of the Express extensions visible to it, which is what would happen if you modified the global prototypes.

I've always thought the current middleware implementation was possibly slower, uses deprecated __proto__, and has more mental overhead to understand/modify.

You can always benchmark it, but JavaScript doesn't provide any other good way to do this without global modifications. Other methods like calling a ton of Object.defineProperty on every request is slower.

@Fishrock123
Copy link
Contributor Author

@NickStefan the pillarjs module this is being extracted to is going to be public soon; I can assure you the implementation is far cleaner than the current. :)

@NickStefan
Copy link

@dougwilson Being able to have an unmodified http res req process alongside of an express app makes sense. I'm sure it gets old answering about the __proto__, but thanks for the explanation.

@Fishrock123 Thanks. Hadn't seen pillarjs yet. Looks promising.

@nelsonpecora
Copy link

@NickStefan Another reason is that certain modules (like node-http2) expect certain http res/req methods.

@rlidwka
Copy link
Member

rlidwka commented Apr 7, 2015

@yoshokatana , so node-http2 inherits its req from another IncomingMessage, right? And two prototype injections sorta conflict with each other?

We probably need a way to specify which class req/res should be inherited from then.

@nelsonpecora
Copy link

Yep. I'm not sure whose responsibility that is, though. I get why express uses its own req/res objects, but I also understand why node-http2 assumes it can inherit it. Not sure what the sanest convention should be in this case.

@dougwilson
Copy link
Contributor

Regarding the http2 discussion, I put a comment over at their repo saying we are willing to make any changes/fixes necessary here if someone wants to open a new issue about this and perhaps an explanation of what the issue is :)

@molnarg
Copy link

molnarg commented May 3, 2015

Yeah the only issue is that node-http2 has a different class (and because of this, different proto for instances) for requests and responses than the built-in HTTP1 implementation. Express changes the proto to an extended version of the built-in IncomingMessage. As per @dougwilson 's comment in molnarg/node-http2#100, I will expect express 5.0 to solve this problem, and make a note about this in the node-http2 readme. Thanks :)

@jokeyrhyme
Copy link

Seems related to #2812 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants