ToothlessGear / node-gcm

A NodeJS wrapper library port to send data to Android devices via Google Cloud Messaging
https://github.com/ToothlessGear/node-gcm
Other
1.3k stars 206 forks source link

Not working in proxy #97

Closed mikkysati closed 8 years ago

mikkysati commented 9 years ago

I am using this behind proxy and have set the environment variables http_proxy and https_proxy. But whenever I try to run the server I get this error:

[Error: tunneling socket could not be established, cause=Parse Error] code: 'ECONNRESET'

pablonazareno commented 9 years ago

I'm having the same issue. It's because in module dependencies, it not specify the version of request module very well. And in latest releases of that module proxy configuration have change. I'm working in a PR #115 to fix this.

mikkysati commented 9 years ago

Nice so to use proxy, do I have to use this line of code? var sender = new gcm.Sender('API KEY',{'proxy':'proxy:port'});

pablonazareno commented 9 years ago

Yes, but in my case this stop working when upgrade to latest version of node-gcm. And I have to add another line to get work again, the one at Pull Request.

mikkysati commented 9 years ago

I tried that code(which is in your Pull Request), still gcm-node is not working.

eladnava commented 8 years ago

@pablonazareno @mikkysati I tracked down the source of the problem when supplying a proxy and found a solution.

The Problem

  1. On sender.js#86, we set a Content-length header.
  2. When setting a proxy for our request, the request module creates an HTTP CONNECT request through the proxy to establish a HTTPS tunnel, but sends the Content-length header along with this request, which is incorrect behavior. The result is that the GCM server is waiting for us to send data in the CONNECT request, when all we wanted to do was open an HTTPS tunnel: fail
  3. The GCM server responds with an error code.

This is caused by the following code, which constructs the request to the GCM API:

    var post_options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-length': Buffer.byteLength(requestBody, 'utf8'),
            'Authorization': 'key=' + this.key
        },
        uri: Constants.GCM_SEND_URI,
        body: requestBody
    };

Since we hard-coded the Content-length header, request sends it with every request, even the CONNECT.

The Solution

The solution is to let request construct these headers on its own by changing the way we configure the request as follows:

    var post_options = {
        method: 'POST',
        headers: {
            'Authorization': 'key=' + this.key
        },
        uri: Constants.GCM_SEND_URI,
        json: JSON.parse(requestBody)
    };

The main difference is that we no longer hard-code the content headers, and supply the JSON payload in the json parameter.

I will submit a PR with this fix when I find some free time.

@hypesystem fyi

hypesystem commented 8 years ago

Cool! Good spot, and will also make our integration with request easier.