Node.js simple http request doesn't work - node.js

I wonder why such simple http request is not working...
http = require("http")
url = "http://nodejs.org/"
console.log "Try a request to #{url}..."
reqHttp = http.request url, (response) ->
console.log "Request to #{url}"
response.on 'data', (chunk) -> console.log "chunk: ", chunk
reqHttp.on 'error', (error) -> console.log "reqHttp error", error
After a minute or so it returns:
reqHttp error { [Error: socket hang up] code: 'ECONNRESET' }
To make sure it is not a problem on my environment, I tried the request module and worked just fine:
request = require("request")
url = "http://nodejs.org/"
request url, (error, response, body) ->
console.log body if not error and response.statusCode is 200
It seems I'm not the only one.
So, I have a workaround for my problem (using request module), but I'd like to know why I can't use the buind-in http request. Is it buggy or unreliable? (Node.js version 0.8.21)

OK, this is really simple. You are constructing an http request but did not finish sending it. From the link you gave itself:
req.write('data\n'); //Write some data into request
req.write('data\n');
req.end(); //Finish sending request let request go. Please do this
Since you never used req.end(), it hung up since it never got completed. Node reset the inactive request
reqHttp error { [Error: socket hang up] code: 'ECONNRESET' }

Related

ETIMEDOUT error when making a request to sendgrid API

I'm using the node js request module to send emails via sendgrid. I am getting the error ETIMEDOUT. I intend on using node-retry npm module to retry the sending, but how can I detect what the error code is? Does the sendgrid API return the error code somehow? Also when I do detect the error code, is it just a matter of waiting X seconds to send the email again? If so how do I determine what X is?
_makeAPIRequest (httpMethod, url, body) {
var defer = Q.defer();
var options = {
method: httpMethod,
url: this.SENDGRID_API_URL + url,
headers: {
'content-type': 'application/json',
authorization: 'Bearer ' + SENDGRID_API_KEY
},
body: body,
json: true
};
request(options, function (error, response, body) {
if (error) {
console.dir(error);
return defer.reject(error);
}
defer.resolve(body);
});
return defer.promise;
}
ETIMEDOUT is an OS error message. It indicates a failed attempt, at the TCP/IP level, to connect to a remote host, probably the one mentioned in SENDGRID_API_URL.
The default value for that is https://api.sendgrid.com/v3/. For some reason, possibly an outbound firewall or some sort of network configuration trouble, your nodejs program cannot reach that URL, and waits for a response. You should check your value of that URL.
If this is intermittent (doesn't happen all the time) you probably can wait a few seconds and try again.
If it starts happening after you've sent a bunch of emails, you may be hitting a limit at sendgrid. Pace out your sending of emails; try putting a half-second delay between them.

NodeJS Server crash when request/response.aborted

When aborting a xmlHttpRequest, sent to a NodeJS-Express server, the server crashes if the request has not been processed finally or the response can't be send, due to a abroted request.
I use a connected-flag to make sure the response is only sent when the connection is up.
I tried to catch these exceptions, but they don't handle the request aborted event:
var connected = true;
req.connection.on('close', function () {
connected = false;
// code to handle connection abort
});
res.on('error', function (err) {
console.log("response couldn't be sent.");
connected = false;
});
if(connected)
res.send(...);
req.connection.removeListener('close', removeCallback);
res.removeListener('error', removeCallback);
Are there any events I can look at to take care of the „Error: Request aborted“ exception, which causes the server to crash?
According to the W3C specs, XMLHttpRequest emits a "abort" event.
http://www.w3.org/TR/XMLHttpRequest/#event-handlers
So basically, you can listen to that event to handle the error, I guess.
Actually, request.on('abort', fn) should work fine for detecting an aborted HTTP request in node.js

NodeJS - “socket hang up” after large amount of requests closing

I have been stuck on this "socket hang up" error for a couple days now, and I was hoping someone could help me.
I currently have two Node programs set up:
An HTTP server in Node that responds with the same data for every
request.
An HTTP server which responds with data from HTTP server 1.
for every request.
My code for HTTP server 2. is below.
var http = require('http')
, https = require('https')
, server = http.createServer(do).listen(801)
function do(req, res) {
var getReq = htts.get('http://127.0.0.1', function (getRes) {
setTimeout(function () {getRes.pipe(res)},1000)
})
req.on('close', function () {
// setTimeout(function () {getReq.abort()},20)
console.log(++i + ': req closed')
getReq.abort()
})
}
The problem is when I send a request to HTTP server 2. and close the request before a response is sent to my browser (I've set a timeout to give me time to abort). If I continually hold down the refresh button, I will receive the "socket hang up" error after an x amount of times, and do not really understand how to fix this. If I set a timer before executing getReq.abort(), the problem happens less often, and if I set the timer to a large number (above 100ms), there isn't an issue at all.
I can consistently replicate the error by executing getReq.abort() right after creating the request, so I believe that it has something to do with aborting between the time the socket is assigned to the request and before the response is sent.
What is wrong with my code, and how do I prevent this from happening?
Thanks

Node.js - Create a proxy, why is request.pipe needed?

Can some one explain this code to create a proxy server. Everything makes sense except the last block. request.pipe(proxy - I don't get that because when proxy is declared it makes a request and pipes its response to the clients response. What am I missing here? Why would we need to pipe the original request to the proxy because the http.request method already makes the request contained in the options var.
var http = require('http');
function onRequest(request, response) {
console.log('serve: ' + request.url);
var options = {
hostname: 'www.google.com',
port: 80,
path: request.url,
method: 'GET'
};
var proxy = http.request(options, function (res) {
res.pipe(response, {
end: true
});
});
request.pipe(proxy, {
end: true
});
}
http.createServer(onRequest).listen(8888);
What am I missing here? [...] the http.request method already makes the request contained in the options var.
http.request() doesn't actually send the request in its entirety immediately:
[...] With http.request() one must always call req.end() to signify that you're done with the request - even if there is no data being written to the request body.
The http.ClientRequest it creates is left open so that body content, such as JSON data, can be written and sent to the responding server:
var req = http.request(options);
req.write(JSON.stringify({
// ...
}));
req.end();
.pipe() is just one option for this, when you have a readable stream, as it will .end() the client request by default.
Although, since GET requests rarely have a body that would need to be piped or written, you can typically use http.get() instead, which calls .end() itself:
Since most requests are GET requests without bodies, Node provides this convenience method. The only difference between this method and http.request() is that it sets the method to GET and calls req.end() automatically.
http.get(options, function (res) {
res.pipe(response, {
end: true
});
});
Short answer: the event loop. I don't want to talk too far out of my ass, and this is where node.js gets both beautiful and complicated, but the request isn't strictly MADE on the line declaring proxy: it's added to the event loop. So when you connect the pipe, everything works as it should, piping from the incoming request > proxy > outgoing response. It's the magic / confusion of asynchronous code!

Tiny server/client setup - server doesn't respond. All code provided

I'm teaching myself Coffeescript/node and, of course, the only way to do this is with TDD. That means I'm also teaching myself vows. There are, I think, at least two problems. One is -- where does the asynchronous code to get the HTTP response lie? And the other is -- why won't the server send me a response back? The console displays "Request sent" but it does not display "Request received."
Here is the test file:
vows = require 'vows'
assert = require 'assert'
EventEmitter = require('events').EventEmitter
Server = require('./web').WebServer
Client = require('../lib/client').Client
Request = require('../lib/request').Request
PORT = 8080
SERVER = new Server PORT
SERVER.start()
CLIENT = new Client PORT, 'localhost'
REQUEST = new Request 'GET', '/'
vows
.describe('Sending a request to the server')
.addBatch
'The request is sent':
topic: ->
CLIENT.transmit(REQUEST, #callback)
return
'The response should be what the server sent back': (err, request) ->
body = ""
request.on 'response', (response) ->
response.on 'data', (chunk) -> body += chunk
assert.equal body, /Ooga/
.export(module)
Here is the WebServer object:
Http = require('http')
exports.WebServer = class WebServer
processRequest = (request, response) ->
console.log 'Request received!'
console.log request
response.writeHead 200, {'Content-Type':'text/plain'} #, 'Content-Length':'6'}
response.write 'Ha-ha!'
response.end
constructor: (#port) ->
#server = Http.createServer processRequest
start: ->
#server.listen #port
stop: ->
#server.close()
Next up is the client code - also very simple.
Http = require 'http'
Request = require('./request').Request
exports.Client = class Client
constructor: (#port, #host) ->
#httpClient = Http.createClient #port, #host
#sentence = "I am a Client"
transmit: (request, callback = null) ->
req = #httpClient.request request.method, request.pathName
req.end
console.log "Request sent!"
if callback
callback(null, req)
#req.on 'response', (res) ->
# callback(null, res)
#request.on 'data', (chunk) -> callback(null, chunk)
#callback(null, request)
And finally, the 'request' object.
exports.Request = class Request
constructor: (#method, #pathName) ->
method: ->
#method
pathName: ->
#pathname
responseBody: ->
#body
setResponseBody: (body) ->
#body = body
appendToResponseBody: (chunk) ->
#body += chunk
All this is so simple that I really can't tell why the server doesn't seem to be working. I'm not even worried, yet, about where the asynchronous code should be to get the information back from the server, but I'd like to figure that out too..
Ah, you've made a classic mistake: You wrote
req.end
where you meant
req.end()
So, your request wasn't actually being sent at all, despite your console's claims to the contrary! (I see a response.end in your code as well.)
Incidentally, Vows test code is pretty, but it's also a complex framework with some subtle gotchas. You may want to try something simpler, like nodeunit.
Oh, and if you really hate parentheses, you can write do req.end instead of req.end(), but this isn't a common style.

Resources