I'm trying to use http.Agent({ keepAlive: true}) on http.request to keep the connection open for future requests.
I created a simple server to log each new connection but when i run my request.js the server logs two new connections.
How can i use the HTTP keep-alive with Node.js native modules?
request.js:
const http = require("http");
const agent = new http.Agent({
keepAlive: true
});
var req1 = http.request({
agent: agent,
method: "GET",
hostname: "localhost",
port: 3000
}, function (res1) {
console.log("REQUEST_1");
var req2 = http.request({
agent: agent,
method: "GET",
hostname: "localhost",
port: 3000
}, function (res2) {
console.log("REQUEST_2");
});
req2.end();
});
req1.end();
server.js:
const http = require('http');
var server = http.createServer(function (req, res) {
res.end('OK');
console.log("REQUEST");
})
server.on('connection', function (socket) {
console.log("NEW CONNECTION");
})
server.listen(3000);
output:
NEW CONNECTION
REQUEST
NEW CONNECTION
REQUEST
Set maxSockets options like this:
const agent = new http.Agent({
keepAlive: true,
maxSockets: 1
});
By default maxSockets is set to Infinity - https://nodejs.org/api/http.html#http_new_agent_options
Full example on node v10
const http = require("http");
const agent = new http.Agent({
keepAlive: true,
maxSockets: 1
});
var req1 = http.request({
agent: agent,
method: "GET",
hostname: "localhost",
port: 3000
}, function (res1) {
console.log("REQUEST_1");
res1.on('data', function () {
console.log("REQUEST_1 data");
});
res1.on('end', function () {
console.log("REQUEST_1 end");
});
var req2 = http.request({
agent: agent,
method: "GET",
hostname: "localhost",
port: 3000
}, function (res2) {
console.log("REQUEST_2");
res2.on('data', function () {
console.log("REQUEST_2 data");
});
res2.on('end', function () {
console.log("REQUEST_2 end");
});
});
req2.end();
});
req1.end();
The accepted answer doesn't make clear that the code posted will allow only one request simultaneously per host per thread.
That is usually not what you want and will lead to requests slowing down waiting for the previous one to complete.
Starting with Node.js v19, the keepAlive option is set to true by default for all outgoing HTTP(s) connections.
You can read more about it on Node.js's v19 documentation.
your demo not set res1's on data listener ,it will cause the socket not be close ,so the second request have to create a new connect to server ,just add a data listener
Related
I am trying to connect to a remote server with socket.io, but I am having some problems. I am getting this error: The value of the Access-Control-Allow-Credentials header in the response is ' ' which must be 'true' when the request's credentials mode is 'include'
OK, so here is the code:
Server
var server = require('http').createServer();
const io = require("socket.io")(server, {
cors: {
origin: "my URL",
methods: ["GET", "POST"],
credentials: false
}
});
io.sockets.on('connection', function(socket) {
console.log("Client has connected!");
});
console.log ('Server started.');
server.listen(3000);
Here is the client code:
var socket = io.connect("https://persistent-gentle-banon.glitch.me", {
withCredentials: false
});
How can I solve this and get it to connect?
Thanks for any help!
i had the same problem, i was using express and i was able to solve it by
var cors = require("cors");
const corsOptions = {
origin: "*",
optionsSuccessStatus: 200
};
const io = require("socket.io")(server, {
cors: {
origin: "*",
methods: ["PUT", "GET", "POST", "DELETE", "OPTIONS"],
credentials: false
}
// transports: ['websocket']
});
app.use(cors(corsOptions));
According to this link https://socket.io/docs/v4/server-instance/#serverengine , you should use io.engine initial_headers and headers events to set cors headers simply, this should work with socket.io v4+.
import { createServer } from "http";
import {Server} from 'socket.io';
const server = createServer(app);
const io = new Server(server);
io.engine.on("initial_headers", (headers, req) => {
headers["Access-Control-Allow-Origin"] = "http://localhost:4200";
});
io.engine.on("headers", (headers, req) => {
headers["Access-Control-Allow-Origin"] = "http://localhost:4200"; // url to all
});
server.listen(3000);
I am trying to send a post request to a service from my node server.
Node is running on http://localhost:3000. The method I am trying to reach is reachable through http://localhost:80/some/adress/business/layer/myMethod.
var options = {
host: 'localhost',
path: '/some/adress/business/layer/myMethod',
port: '80',
method: 'POST',
headers: {
'Content-type': 'application/json',
'Content-Length': data.length
}
};
var req = http.request(options, function (resu) {
console.log('statusCode: ' + res.statusCode)
resu.on('data', function (d) {
console.log(d);
});
resu.on('error', function (err) {
console.log(err);
});
resu.on('end', function () {
res.jsonp({ result: true });
res.end();
});
});
req.write("data");
req.end();
The request works fine, well more or less. I am getting a 401 status back. The question is: How can I send windows credentials from node to the named server running on localhost:80... ?
Without knowing the exact details of your setup, I can't be sure, but you probably need to use NTLM authentication. There are several libraries that do this for node. Take a look at this question. Hope this helps!
I'm trying to load weather data. I have front end code that was doing this perfectly but I need to move this to back end. I moved a library of my functions over to Node.JS. I was using $.getJSON but was told I should use https.request for the new version. Here's my code:
getTextWeatherUsingStationUsingRequest: function(theStation){
const http = require("http");
const https = require("https");
thePath = 'stations/' + theStation + '/observations/current';
// theURL = 'https://api.weather.gov/stations/' + theStation + '/observations/current';
function requestTheData(){
var options = {
protocol: "https:",
hostname: "https://api.weather.gov/",
path: thePath,
port: 80,
method: "GET"
};
var instaRequest = https.request(options);
instaRequest.on("response", function(res){
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
console.log("response");
console.log(res.statusCode);
console.log(res.statusMessage);
});
instaRequest.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
instaRequest.end();
}
requestTheData();
I'm getting this error and can't figure out what's going on:
problem with request: getaddrinfo ENOTFOUND https://api.weather.gov/stations/ https://api.weather.gov/stations/:80
HTTPS generally uses port 443, so lets change that. Also, the API shows the hostname should be the raw URL and the path should be the remainder of the route (with a leading slash) similar to this:
thePath = '/stations/' + theStation + '/observations/current';
...
var options = {
hostname: "api.weather.gov",
path: thePath,
port: 443,
method: "GET"
};
Before even seeing any answers I got it working by:
protocol: "https:",
hostname: "api.weather.gov",
but then I was getting a STATUS:
403 Forbidden You don't have permission to access
"http://api.weather.gov/" on this server.
I seemed to remember that you are required to pass something in through headers so I added this under "method: "GET","
method: "GET",
headers: {
'Accept' : 'application/json',
'Content-Type': 'application/json',
'User-Agent' : 'MY-UA-STRING'
}
And, voila, now I'm getting JSON weather data. It didn't work until I added the 'User-Agent'. Do you guys know what this needs to be (and/or point me to a place that describes this)?
I am creating a system that passes http request to a child process in Node js. I cant pass the child process the active Socket using child.send( 'socket', req.socket ) but inside the child I want to recreate the http request and response objects so that they have the headers, parameters, cookies etc.
I am using Express, so if I can recreate the Express req and res object it's even better.
I have been fiddling a bit, but no success.
If I do the following it creates the IncomingMessage object but the headers etc are empty.
var http = require('http');
/* Child Process recieves the Socket */
var incomingMessage = new http.IncomingMessage( socket );
Any ideas if there is any way to accomplish what I want?
You can also this trick for tunneling:
let agent;
if (protocol == 'https:')
agent = new https.Agent();
else
agent = new http.Agent();
agent.createConnection = (opts, callback) => callback(false, socket);
const req = http.request({
method: method,
host: host,
port: port,
protocol: protocol,
path: path,
headers: headers,
agent: agent
}, function (res)
{
console.log(res.headers);
console.log(res.socket.remoteAddress);
console.log(res.socket == socket); // true
});
req.end();
I have a problem
server:
var connect = require('connect');
var http = require('http');
var app = connect()
.use(connect.limit('32kb'))
.use(connect.urlencoded())
.use(connect.json())
.use(function(req, res){
console.log('yo');
res.end('hello\n');
});
http.createServer(app).listen(3000);
client:
var http = require('http');
var req = http.request({
method: 'POST',
port: 3000,
headers: {
'Content-Type': 'application/json'
}
});
req.write('[');
var n = 30000000;
while (n--) {
req.write('"foo",');
}
req.write('"bar"]');
req.end();
Connect's middleware limit not "limiting" size of json. I know that it will deprecated, but instead Express framework what can i use to limit a size of requests?
do this instead:
.use(connect.urlencoded({
limit: '32kb'
}))
.use(connect.json({
limit: '32kb'
}))
or just:
.use(connect.bodyParser({
limit: '32kb'
})
you can still write to req, but that doesn't necessarily mean the server will receive those bytes. if you check the response and it isn't a 4xx error, then it's a bug.
EDIT:
req.once('response', function (res) {
assert.equal(res.statusCode, 413)
})
.write(new Buffer(123123123213223122))
.end()
the limit middleware checks the header Content-Length of request message only while there's no such header out of your HTTP POST request.
You can verify this by using:
var app = connect()
.use(connect.limit('32kb'))
.use(connect.urlencoded())
.use(connect.json())
.use(function(req, res){
console.log(req.headers);
console.log('yo');
res.end('hello\n');
});
You can test the limit middle via this code:
var http = require('http');
var req = http.request({
method: 'POST',
port: 3000,
headers: {
'Content-Type': 'application/json',
'Content-Length': 40 * 1024
}
});
BTW: you can check how the limit middleware is tested: https://github.com/senchalabs/connect/blob/master/test/limit.js