Sorry, the diff of this file is not supported yet
| language: node_js | ||
| node_js: | ||
| - "0.11" | ||
| - "0.10" | ||
| notifications: | ||
| email: false |
| # Guidelines for contributing code | ||
| New Relic welcomes code contributions by the Node community to this module, and | ||
| have taken effort to make this process easy for both contributors and our | ||
| development team. | ||
| When contributing, keep in mind that New Relic customers (that's you!) are | ||
| running many different versions of Node, some of them pretty old (most of you | ||
| have moved off 0.6, but there are more than a few 0.8 applications still out | ||
| there). Changes that depend on the newest version of Node will probably be | ||
| rejected, with prejudice if they replace something backwards compatible. | ||
| ## And finally... | ||
| You are welcome to send pull requests to us - however, by doing so you agree | ||
| that you are granting New Relic a non-exclusive, non-revokable, no-cost license | ||
| to use the code, algorithms, patents, and ideas in that code in our products if | ||
| we so choose. You also agree the code is provided as-is and you provide no | ||
| warranties as to its fitness or correctness for any purpose. |
+20
| Copyright Joyent, Inc. and other Node contributors. | ||
| Permission is hereby granted, free of charge, to any person obtaining a | ||
| copy of this software and associated documentation files (the | ||
| "Software"), to deal in the Software without restriction, including | ||
| without limitation the rights to use, copy, modify, merge, publish, | ||
| distribute, sublicense, and/or sell copies of the Software, and to permit | ||
| persons to whom the Software is furnished to do so, subject to the | ||
| following conditions: | ||
| The above copyright notice and this permission notice shall be included | ||
| in all copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | ||
| NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
| DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| USE OR OTHER DEALINGS IN THE SOFTWARE. |
+153
| ## yakaa: yet another keep-alive agent | ||
| This is an extracted copy of Node 0.12's keep-alive Agent implementation with | ||
| some small changes intended to make it work with older versions of Node. It | ||
| also has one extra feature, which I needed. | ||
| The HTTP Agent is used for pooling sockets used in HTTP client requests. | ||
| The HTTP Agent also defaults client requests to using Connection:keep-alive. If | ||
| no pending HTTP requests are waiting on a socket to become free the socket is | ||
| closed. This means that Node's pool has the benefit of keep-alive when under | ||
| load but still does not require developers to manually close the HTTP clients | ||
| using KeepAlive. | ||
| If you opt into using HTTP KeepAlive, you can create an Agent object with that | ||
| flag set to `true`. (See the [constructor options](#http_new_agent_options) | ||
| below.) Then, the Agent will keep unused sockets in a pool for later use. | ||
| They will be explicitly marked so as to not keep the Node process running. | ||
| However, it is still a good idea to explicitly | ||
| [`destroy()`](#http_agent_destroy) KeepAlive agents when they are no longer in | ||
| use, so that the Sockets will be shut down. | ||
| Sockets are removed from the agent's pool when the socket emits either a | ||
| "close" event or a special "agentRemove" event. This means that if you intend | ||
| to keep one HTTP request open for a long time and don't want it to stay in the | ||
| pool you can do something along the lines of: | ||
| http.get(options, function(res) { | ||
| // Do stuff | ||
| }).on("socket", function (socket) { | ||
| socket.emit("agentRemove"); | ||
| }); | ||
| ### var Agent = require('yakaa'); new Agent([options]) | ||
| * `options` {Object} Set of configurable options to set on the agent. | ||
| Can have the following fields: | ||
| * `keepAlive` {Boolean} Keep sockets around in a pool to be used by | ||
| other requests in the future. Default = `false` | ||
| * `keepAliveMsecs` {Integer} When using HTTP KeepAlive, how often | ||
| to send TCP KeepAlive packets over sockets being kept alive. | ||
| Default = `1000`. Only relevant if `keepAlive` is set to `true`. | ||
| * **ADDED** `keepAliveTimeoutMsecs` {Integer} When using HTTP KeepAlive, how | ||
| long to keep the socket connected without activity before it gets reaped. | ||
| * `maxSockets` {Number} Maximum number of sockets to allow per | ||
| host. Default = `Infinity`. | ||
| * `maxFreeSockets` {Number} Maximum number of sockets to leave open | ||
| in a free state. Only relevant if `keepAlive` is set to `true`. | ||
| Default = `256`. | ||
| The default `http.globalAgent` that is used by `http.request` has all | ||
| of these values set to their respective defaults. | ||
| To configure any of them, you must create your own `Agent` object. | ||
| ```javascript | ||
| var http = require('http'); | ||
| var Agent = require('yakaa'); | ||
| var keepAliveAgent = new Agent({ keepAlive: true }); | ||
| keepAliveAgent.request(options, onResponseCallback); | ||
| ``` | ||
| ### agent.maxSockets | ||
| By default set to Infinity. Determines how many concurrent sockets the agent | ||
| can have open per origin. Origin is either a 'host:port' or | ||
| 'host:port:localAddress' combination. | ||
| ### agent.maxFreeSockets | ||
| By default set to 256. For Agents supporting HTTP KeepAlive, this | ||
| sets the maximum number of sockets that will be left open in the free | ||
| state. | ||
| ### agent.sockets | ||
| An object which contains arrays of sockets currently in use by the | ||
| Agent. Do not modify. | ||
| ### agent.freeSockets | ||
| An object which contains arrays of sockets currently awaiting use by | ||
| the Agent when HTTP KeepAlive is used. Do not modify. | ||
| ### agent.requests | ||
| An object which contains queues of requests that have not yet been assigned to | ||
| sockets. Do not modify. | ||
| ### agent.destroy() | ||
| Destroy any sockets that are currently in use by the agent. | ||
| It is usually not necessary to do this. However, if you are using an | ||
| agent with KeepAlive enabled, then it is best to explicitly shut down | ||
| the agent when you know that it will no longer be used. Otherwise, | ||
| sockets may hang open for quite a long time before the server | ||
| terminates them. | ||
| ### agent.getName(options) | ||
| Get a unique name for a set of request options, to determine whether a | ||
| connection can be reused. In the http agent, this returns | ||
| `host:port:localAddress`. In the https agent, the name includes the | ||
| CA, cert, ciphers, and other HTTPS/TLS-specific options that determine | ||
| socket reusability. | ||
| ## new Agent.SSL(options) | ||
| An Agent object for HTTPS similar to Agent. | ||
| `options` is an object. All options from Agent are valid. | ||
| The following options from [tls.connect()][] can also be used. | ||
| - `pfx`: Certificate, Private key and CA certificates to use for SSL. Default `null`. | ||
| - `key`: Private key to use for SSL. Default `null`. | ||
| - `passphrase`: A string of passphrase for the private key or pfx. Default `null`. | ||
| - `cert`: Public x509 certificate to use. Default `null`. | ||
| - `ca`: An authority certificate or array of authority certificates to check | ||
| the remote host against. | ||
| - `ciphers`: A string describing the ciphers to use or exclude. Consult | ||
| <http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT> for | ||
| details on the format. | ||
| - `rejectUnauthorized`: If `true`, the server certificate is verified against | ||
| the list of supplied CAs. An `'error'` event is emitted if verification | ||
| fails. Verification happens at the connection level, *before* the HTTP | ||
| request is sent. Default `true`. | ||
| - `secureProtocol`: The SSL method to use, e.g. `SSLv3_method` to force | ||
| SSL version 3. The possible values depend on your installation of | ||
| OpenSSL and are defined in the constant [SSL_METHODS][]. | ||
| Example: | ||
| ```js | ||
| var SSLAgent = require('yakaa').SSL; | ||
| var options = { | ||
| hostname: 'encrypted.google.com', | ||
| port: 443, | ||
| path: '/', | ||
| method: 'GET', | ||
| key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), | ||
| cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem') | ||
| }; | ||
| options.agent = new SSLAgent(options); | ||
| ``` | ||
| ### LICENSE | ||
| See LICENSE in this distribution. As code derived from Node's source, it's | ||
| governed by the same license as Node itself. |
+20
| # How to contact us | ||
| Please send any issue that you feel affects the security of this module to | ||
| **security@newrelic.com**. | ||
| # Expectations | ||
| If we do not respond promptly, we ask that you give us the benefit of the | ||
| doubt, as it is possible the email went to spam or we have been so focused on | ||
| something else we haven't seen it yet. Please send us a quick message, | ||
| *without detail* to one of the following: | ||
| * An issue here on GitHub, with an email address we can use to contact you | ||
| for a more detailed report. | ||
| * Message [@newrelic](https://twitter.com/newrelic) on Twitter. | ||
| * Give our engineering team a heads up on IRC in #newrelic on Freenode. | ||
| # History | ||
| No security issues have been reported for this project yet. |
| var test = require('tap').test; | ||
| var Agent = require('../index.js') | ||
| var http = require('http') | ||
| test("yakaa should destroy the socket after an error", function (t) { | ||
| t.plan(2); | ||
| // set a super short socket lifetime | ||
| // normally this would kill a TLS session, | ||
| // but our super simple test won't mind | ||
| var agent = new Agent({keepAlive : true}); | ||
| var opts = { | ||
| port : 1, | ||
| agent : agent, | ||
| }; | ||
| agent.on('yakaa_remove', function () { | ||
| t.ok(true, 'removed'); | ||
| }) | ||
| var req = new http.ClientRequest(opts); | ||
| req.on('error', function (err) { | ||
| t.ok(err); | ||
| }) | ||
| req.end(); | ||
| }); |
| var test = require('tap').test; | ||
| var Agent = require('../index.js') | ||
| var http = require('http') | ||
| var web = http.createServer(function(req,res){req.pipe(process.stdout); res.end()}); | ||
| test("yakaa should reuse the socket", function (t) { | ||
| t.plan(7); | ||
| web.listen(); | ||
| var PORT = web.address().port; | ||
| var agent = new Agent({keepAlive : true, keepAliveTimeoutMsecs: 100}); | ||
| var opts = { | ||
| port : PORT, | ||
| agent : agent, | ||
| }; | ||
| var socket; | ||
| var i = 0; | ||
| agent.on('free', function (sock, opts) { | ||
| t.ok(i++ < 2, 'free socket'); | ||
| }); | ||
| // only destroyed once at the end | ||
| var j = 0; | ||
| agent.on('yakaa_destroy', function (s) { | ||
| t.ok(j++ < 1, 'destroy'); | ||
| t.equals(j,1, 'destroy called once') | ||
| t.equals(i,2, 'free called twice') | ||
| t.end() | ||
| }); | ||
| new http.ClientRequest(opts, next).end(); | ||
| function next(res) { | ||
| res.pipe(process.stdout) | ||
| t.ok(res, 'first response'); | ||
| // set short timeout so this test ends quickly | ||
| new http.ClientRequest(opts, done).end(); | ||
| } | ||
| function done(res) { | ||
| res.pipe(process.stdout); | ||
| t.ok(res, 'second response'); | ||
| web.close(); | ||
| } | ||
| }); | ||
| test("yakaa should destroy the socket after each request", function (t) { | ||
| t.plan(8); | ||
| web.listen(); | ||
| var PORT = web.address().port; | ||
| // set a super short socket lifetime | ||
| // normally this would kill a TLS session, | ||
| // but our super simple test won't mind | ||
| var agent = new Agent({keepAlive : true, keepAliveTimeoutMsecs: 1}); | ||
| var opts = { | ||
| port : PORT, | ||
| agent : agent, | ||
| }; | ||
| var j=0; | ||
| agent.on('yakaa_destroy', function () { | ||
| t.ok(j++ < 2, 'destroy'); | ||
| if (j==2) { | ||
| t.equals(j,2, 'destroy called twice') | ||
| t.equals(i,2, 'free called twice') | ||
| t.end(); | ||
| } | ||
| }) | ||
| var i=0; | ||
| agent.on('free', function (sock, opts) { | ||
| t.ok(i++ < 2, 'free socket'); | ||
| }); | ||
| new http.ClientRequest(opts, next).end(); | ||
| function next(res) { | ||
| res.pipe(process.stdout) | ||
| t.ok(res, 'first response'); | ||
| setTimeout(function () { | ||
| new http.ClientRequest(opts, done).end(); | ||
| }, 10); | ||
| } | ||
| function done(res) { | ||
| res.pipe(process.stdout); | ||
| t.ok(res, 'second response'); | ||
| web.close(); | ||
| } | ||
| }); |
+15
-23
@@ -112,17 +112,10 @@ 'use strict'; | ||
| // Avoid duplicate timeout events by removing timeout listeners set | ||
| // on socket by previous requests. node does not do this normally | ||
| // because it assumes sockets are too short-lived for it to matter. | ||
| // It becomes a problem when sockets are being reused. Fixed sometime | ||
| // around Node 0.10.0. | ||
| // | ||
| // See https://github.com/joyent/node/commit/451ff1540 | ||
| if (self.keepAliveTimeoutMsecs && | ||
| socket._events && | ||
| Array.isArray(socket._events.timeout)) { | ||
| socket.removeAllListeners('timeout'); | ||
| // Restore the socket's setTimeout() that was remove as collateral | ||
| // damage. | ||
| socket.setTimeout(self.keepAliveTimeoutMsecs, socket._reapTimeout); | ||
| // set timeout on idle sockets | ||
| if (options.keepAliveTimeoutMsecs !== undefined) { | ||
| socket._yakaa_timeout = setTimeout(function () { | ||
| self.emit('yakaa_destroy'); | ||
| socket.destroySoon(); | ||
| }, options.keepAliveTimeoutMsecs); | ||
| } | ||
| } | ||
@@ -187,2 +180,8 @@ } else { | ||
| // mark socket as non-idle so it doesn't get destroyed mid-request | ||
| if (socket._yakaa_timeout) { | ||
| clearTimeout(socket._yakaa_timeout); | ||
| delete socket._yakaa_timeout; | ||
| } | ||
| // don't leak | ||
@@ -240,11 +239,2 @@ if (!this.freeSockets[name].length) | ||
| if (options.keepAliveTimeoutMsecs) { | ||
| s._reapTimeout = function () { | ||
| debug('_reapTimeout, socket destroy()'); | ||
| s.destroy(); | ||
| self.removeSocket(s, options); | ||
| }; | ||
| s.setTimeout(options.keepAliveTimeoutMsecs, s._reapTimeout); | ||
| } | ||
| function onFree() { | ||
@@ -283,2 +273,4 @@ self.emit('free', s, options); | ||
| this.emit('yakaa_remove', s); | ||
| // If the socket was destroyed, remove it from the free buffers too. | ||
@@ -285,0 +277,0 @@ if (s.destroyed) |
+6
-3
| { | ||
| "name": "yakaa", | ||
| "version": "0.0.1", | ||
| "version": "1.0.0", | ||
| "description": "Yet Another Keep-Alive Agent", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
| "test": "tap test" | ||
| }, | ||
@@ -26,3 +26,6 @@ "repository": { | ||
| }, | ||
| "homepage": "https://github.com/newrelic/yakaa" | ||
| "homepage": "https://github.com/newrelic/yakaa", | ||
| "devDependencies": { | ||
| "tap": "^0.4.8" | ||
| } | ||
| } |
Network access
Supply chain riskThis module accesses the network.
Found 3 instances in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
26139
72.92%13
160%492
22.39%0
-100%0
-100%154
Infinity%1
Infinity%4
100%