Skip to content

Why writeStatusCode is using res.writeHead() instead of res.statusCode? #680

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

Open
banduk opened this issue Aug 15, 2014 · 8 comments
Open

Comments

@banduk
Copy link

banduk commented Aug 15, 2014

Hi guys,

I was trying to sign a header (using its contents) but could not find a good way.
But setting the statusCode variable instead of using res.statusCode() function did the trick.

I was just wondering if there`s a reason why this is being done this way.

@jcrugzz
Copy link
Contributor

jcrugzz commented Aug 15, 2014

@banduk could you give me an example of how you are using it?

@banduk
Copy link
Author

banduk commented Aug 15, 2014

Sure, here's my piece of code.
The signResponse method sign the response based on req, res and data.

With writeStatusCode using res.writeHead() I cannot write into header once it's closed for writing.

  // Sign the response
  proxy.on('proxyRes', function (proxyRes, req, res) {
    proxyRes.on('data', function(data){
      // Here's where I need to insert another header
      signResponse(req, res, data)
      res.status(200);
      res.end(data);
    });
  });

  var appHost     = process.env.APP_HOST;
  var appPort     = process.env.APP_PORT;
  var appProtocol = process.env.APP_PROTOCOL;

  app.all('*',
    passport.authenticate('token', {
      session: false
    }),
    function(req, res) {
      proxy.web(req, res, {
        target: {
          protocol: appProtocol,
          host: appHost,
          port: appPort
        }
      });
    }
  );

@jcrugzz
Copy link
Contributor

jcrugzz commented Aug 15, 2014

@banduk in this case its the app that you are proxying to that would have already written the headers, not http-proxy itself. This is all we do. http-proxy is just finishing the reverse proxy while you attempt to hijack it in the proxyRes event. What you are trying to do is not currently possible with the api. Its currently not possible to intercept the stream before its piped into the original response but this is something I have thought about.

Would allowing it to be possible to inject a transform stream before returning the response solve your problem?

@banduk
Copy link
Author

banduk commented Aug 15, 2014

@jcrugzz, that's what thought; that this is not what http-proxy do...

I'm using http-proxy as an OAuth Proxy, So I need to verify from the req and sign res. If the transformation your suggesting are like this, I don't think it would be useful as it would not allow me to modify the header (am I right?)

@jcrugzz
Copy link
Contributor

jcrugzz commented Aug 16, 2014

@banduk well what i realized is that any of these custom transform streams would need to also inherit from an actual request and response object and automatically pass along headers on('pipe'). There needs to be a module around this to make it possible. I believe it would allow you to modify the header as there wouldn't be a race condition on whether they were sent already or not.

@mbanduk
Copy link

mbanduk commented Aug 18, 2014

@jcrugzz So I'm sure this solves my problem, yes..
I'm just starting to code on node and I'm not yet coding fluently. Could you please gimme some hints on how to make it work before this 'after hooks' are implemented into master branch?

@jcrugzz
Copy link
Contributor

jcrugzz commented Aug 18, 2014

@mbanduk there is no way to do that currently using this module since we strictly do a reverse proxy and thats it. You'd have to replicate the logic that you need in the reverse proxy until these hooks exist.

@banduk
Copy link
Author

banduk commented Aug 19, 2014

@jcrugzz , this code allow me to do what I want. Would it be a good alternative?

  ...
    (options.buffer || req).pipe(proxyReq);

    proxyReq.on('response', function(proxyRes) {
      if(server) { server.emit('proxyRes', proxyRes, req, res); }
      for(var i=0; i < web_o.length; i++) {
       if(web_o[i](req, res, proxyRes)) { break; }
      }

      // Allow us to listen when the proxy has completed
      proxyRes.on('end', function () {
        if (!clb) {
          server.emit('end', req, res, proxyRes);
        }
      })

      // Here are the changes
      if(options.after && typeof options.after === 'function' && options.after.super_ === Transform){
        var after = new options.after({req: req, res: res, proxyRes: proxyRes});
        proxyRes.pipe(after).pipe(res);
      }
      else{
        proxyRes.pipe(res);
      }
    ...

and then calling:

  function SignRequest(options) {
    if (!(this instanceof SignRequest))
      return new SignRequest(options);

    Transform.call(this, options);
    this.options = options;
  }
  util.inherits(SignRequest, Transform);

  SignRequest.prototype._transform = function(chunk, encoding, done) {
    sign(this.options.req, this.options.res, this.options.proxyRes);
    this.push(this.options.proxyRes.body);
    done();
  };

  app.all('*',
      proxy.web(req, res, {
        target: {
          protocol: appProtocol,
          host:     appHost,
          port:     appPort
        },
        after: SignRequest
      });
  );

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

No branches or pull requests

3 participants