aboutsummaryrefslogtreecommitdiff
path: root/node_modules/algoliasearch/src/server/builds
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2018-11-08 00:38:48 +0800
committerruki <waruqi@gmail.com>2018-11-07 21:53:09 +0800
commit26105034da4fcce7ac883c899d781f016559310d (patch)
treec459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/algoliasearch/src/server/builds
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/algoliasearch/src/server/builds')
-rw-r--r--node_modules/algoliasearch/src/server/builds/AlgoliaSearchServer.js78
-rw-r--r--node_modules/algoliasearch/src/server/builds/get-agent.js107
-rw-r--r--node_modules/algoliasearch/src/server/builds/node.js318
3 files changed, 503 insertions, 0 deletions
diff --git a/node_modules/algoliasearch/src/server/builds/AlgoliaSearchServer.js b/node_modules/algoliasearch/src/server/builds/AlgoliaSearchServer.js
new file mode 100644
index 00000000..c6e5dfec
--- /dev/null
+++ b/node_modules/algoliasearch/src/server/builds/AlgoliaSearchServer.js
@@ -0,0 +1,78 @@
+'use strict';
+
+// Some methods only accessible server side
+
+module.exports = AlgoliaSearchServer;
+
+var inherits = require('inherits');
+
+var AlgoliaSearch = require('../../AlgoliaSearch');
+
+function AlgoliaSearchServer(applicationID, apiKey, opts) {
+ // Default protocol is https: on the server, to avoid leaking admin keys
+ if (opts.protocol === undefined) {
+ opts.protocol = 'https:';
+ }
+
+ AlgoliaSearch.apply(this, arguments);
+}
+
+inherits(AlgoliaSearchServer, AlgoliaSearch);
+
+/*
+ * Allow to use IP rate limit when you have a proxy between end-user and Algolia.
+ * This option will set the X-Forwarded-For HTTP header with the client IP and the X-Forwarded-API-Key with the API Key having rate limits.
+ * @param adminAPIKey the admin API Key you can find in your dashboard
+ * @param endUserIP the end user IP (you can use both IPV4 or IPV6 syntax)
+ * @param rateLimitAPIKey the API key on which you have a rate limit
+ */
+AlgoliaSearchServer.prototype.enableRateLimitForward = function(adminAPIKey, endUserIP, rateLimitAPIKey) {
+ this._forward = {
+ adminAPIKey: adminAPIKey,
+ endUserIP: endUserIP,
+ rateLimitAPIKey: rateLimitAPIKey
+ };
+};
+
+/*
+ * Disable IP rate limit enabled with enableRateLimitForward() function
+ */
+AlgoliaSearchServer.prototype.disableRateLimitForward = function() {
+ this._forward = null;
+};
+
+/*
+ * Specify the securedAPIKey to use with associated information
+ */
+AlgoliaSearchServer.prototype.useSecuredAPIKey = function(securedAPIKey, securityTags, userToken) {
+ this._secure = {
+ apiKey: securedAPIKey,
+ securityTags: securityTags,
+ userToken: userToken
+ };
+};
+
+/*
+ * If a secured API was used, disable it
+ */
+AlgoliaSearchServer.prototype.disableSecuredAPIKey = function() {
+ this._secure = null;
+};
+
+AlgoliaSearchServer.prototype._computeRequestHeaders = function(additionalUA) {
+ var headers = AlgoliaSearchServer.super_.prototype._computeRequestHeaders.call(this, additionalUA);
+
+ if (this._forward) {
+ headers['x-algolia-api-key'] = this._forward.adminAPIKey;
+ headers['x-forwarded-for'] = this._forward.endUserIP;
+ headers['x-forwarded-api-key'] = this._forward.rateLimitAPIKey;
+ }
+
+ if (this._secure) {
+ headers['x-algolia-api-key'] = this._secure.apiKey;
+ headers['x-algolia-tagfilters'] = this._secure.securityTags;
+ headers['x-algolia-usertoken'] = this._secure.userToken;
+ }
+
+ return headers;
+};
diff --git a/node_modules/algoliasearch/src/server/builds/get-agent.js b/node_modules/algoliasearch/src/server/builds/get-agent.js
new file mode 100644
index 00000000..cbe003b4
--- /dev/null
+++ b/node_modules/algoliasearch/src/server/builds/get-agent.js
@@ -0,0 +1,107 @@
+'use strict';
+
+// this module will either get a regular http keepalive agent or
+// a proxying agent if `HTTP_PROXY` or `HTTPS_PROXY` environment variables
+// are set
+// request/request module could have been used but it does not do any
+// keepalive on POST requests https://github.com/request/request/issues/236#issuecomment-94587587
+
+module.exports = getAgent;
+
+function getAgent(protocol) {
+ var agent;
+
+ if (protocol !== 'http:' && protocol !== 'https:') {
+ throw new Error('get-agent: `protocol` must be `http:` or `https:`');
+ }
+
+ var parsedProxy = getParsedProxy();
+
+ if (parsedProxy.protocol) {
+ agent = getProxyingAgent(protocol, parsedProxy);
+ } else {
+ // no proxy given, let's use regular keepalived agents
+ agent = getKeepaliveAgent(protocol);
+ }
+
+ return agent;
+}
+
+function getParsedProxy() {
+ var url = require('url');
+ var proxy = process.env.HTTP_PROXY ||
+ process.env.HTTPS_PROXY ||
+ '';
+
+ return url.parse(proxy);
+}
+
+function getKeepaliveAgent(protocol) {
+ var http = require('http');
+ var https = require('https');
+
+ var HttpsAgent = require('agentkeepalive').HttpsAgent;
+ var HttpAgent = require('agentkeepalive');
+ var semver = require('semver');
+
+ var keepAliveAgent;
+
+ // node 0.10 => agentkeepalive
+ // node >= 0.12 => native keepalive
+ // iojs => native keepalive
+ // node >= 0.11.4 has good keepAlive https://github.com/joyent/node/commit/b5b841
+ if (semver.satisfies(process.version, '<0.11.4')) {
+ if (protocol === 'http:') {
+ keepAliveAgent = new HttpAgent({
+ maxSockets: Infinity
+ });
+ } else if (protocol === 'https:') {
+ keepAliveAgent = new HttpsAgent({
+ maxSockets: Infinity
+ });
+ }
+ } else if (protocol === 'http:') {
+ keepAliveAgent = new http.Agent({
+ keepAlive: true,
+ maxSockets: Infinity
+ });
+ } else if (protocol === 'https:') {
+ keepAliveAgent = new https.Agent({
+ keepAlive: true,
+ maxSockets: Infinity
+ });
+ }
+
+ return keepAliveAgent;
+}
+
+function getProxyingAgent(protocol, parsedProxy) {
+ var tunnel = require('tunnel-agent');
+
+ var agentSettings = {
+ maxSockets: Infinity,
+ proxy: {
+ host: parsedProxy.hostname,
+ port: parseInt(parsedProxy.port, 10),
+ proxyAuth: parsedProxy.auth
+ }
+ };
+
+ // httpOverHttps
+ // httpsOverHttps
+ // https://github.com/mikeal/tunnel-agent/blob/912a7a6d00e10ec76baf9c9369de280fa5badef3/index.js#L12-L15
+ var tunnelType = protocol.replace(':', '') +
+ 'Over' +
+ parsedProxy.protocol.replace(':', '').replace('h', 'H');
+
+ var agent = new tunnel[tunnelType](agentSettings);
+
+ // `tunnel-agent` does not have a destroy method
+ agent.destroy = function() {
+ this.sockets.forEach(function(socket) {
+ socket.destroy();
+ });
+ };
+
+ return agent;
+}
diff --git a/node_modules/algoliasearch/src/server/builds/node.js b/node_modules/algoliasearch/src/server/builds/node.js
new file mode 100644
index 00000000..11b806ff
--- /dev/null
+++ b/node_modules/algoliasearch/src/server/builds/node.js
@@ -0,0 +1,318 @@
+'use strict';
+
+// This is the Node.JS entry point
+module.exports = algoliasearch;
+
+var debug = require('debug')('algoliasearch:nodejs');
+var crypto = require('crypto');
+var zlib = require('zlib');
+
+var inherits = require('inherits');
+var Promise = global.Promise || require('es6-promise').Promise;
+var semver = require('semver');
+var isNotSupported = semver.satisfies(process.version, '<0.10');
+var isNode010 = semver.satisfies(process.version, '=0.10');
+var places = require('../../places.js');
+
+var AlgoliaSearchServer = require('./AlgoliaSearchServer');
+var errors = require('../../errors');
+
+// does not work on node <= 0.8
+if (isNotSupported) {
+ throw new errors.AlgoliaSearchError('Node.js version ' + process.version + ' is not supported');
+}
+
+if (process.env.NODE_ENV === 'debug') {
+ require('debug').enable('algoliasearch*');
+}
+
+debug('loaded the Node.js client');
+
+function algoliasearch(applicationID, apiKey, opts) {
+ var cloneDeep = require('../../clone.js');
+ var reduce = require('reduce');
+
+ if (!opts) {
+ opts = {};
+ }
+
+ var httpAgent = opts.httpAgent;
+
+ opts = cloneDeep(reduce(opts, allButHttpAgent, {}));
+
+ // as an httpAgent is an object with methods etc, we take a reference to
+ // it rather than cloning it like other values
+ function allButHttpAgent(filteredOpts, val, keyName) {
+ if (keyName !== 'httpAgent') {
+ filteredOpts[keyName] = val;
+ }
+
+ return filteredOpts;
+ }
+
+ opts.httpAgent = httpAgent;
+
+ opts.timeouts = opts.timeouts || {
+ connect: 2 * 1000,
+ read: 5 * 1000,
+ write: 30 * 1000
+ };
+
+ if (opts.protocol === undefined) {
+ opts.protocol = 'https:';
+ }
+
+ opts._ua = opts._ua || algoliasearch.ua;
+ opts._useCache = false;
+
+ return new AlgoliaSearchNodeJS(applicationID, apiKey, opts);
+}
+
+algoliasearch.version = require('../../version.js');
+algoliasearch.ua = 'Algolia for Node.js ' + algoliasearch.version;
+algoliasearch.initPlaces = places(algoliasearch);
+
+function AlgoliaSearchNodeJS(applicationID, apiKey, opts) {
+ var getAgent = require('./get-agent');
+
+ // call AlgoliaSearchServer constructor
+ AlgoliaSearchServer.apply(this, arguments);
+
+ this._Agent = opts.httpAgent || getAgent(opts.protocol);
+}
+
+inherits(AlgoliaSearchNodeJS, AlgoliaSearchServer);
+
+AlgoliaSearchNodeJS.prototype._request = function request(rawUrl, opts) {
+ var http = require('http');
+ var https = require('https');
+ var url = require('url');
+
+ var client = this;
+
+ return new Promise(function doReq(resolve, reject) {
+ opts.debug('url: %s, method: %s, timeouts: %j', rawUrl, opts.method, opts.timeouts);
+
+ var body = opts.body;
+
+ var parsedUrl = url.parse(rawUrl);
+ var requestOptions = {
+ hostname: parsedUrl.hostname,
+ port: parsedUrl.port,
+ method: opts.method,
+ path: parsedUrl.path,
+ agent: client._Agent
+ };
+
+ var timedOut = false;
+ var timeoutId;
+ var req;
+
+ if (parsedUrl.protocol === 'https:') {
+ // we do not rely on any "smart" port computing by either node.js
+ // or a custom http agent, because:
+ // https://github.com/TooTallNate/node-https-proxy-agent/issues/7#issuecomment-119539690
+ if (requestOptions.port === null) {
+ requestOptions.port = 443;
+ }
+ req = https.request(requestOptions);
+ } else {
+ // same reason to set the port as `https:`
+ if (requestOptions.port === null) {
+ requestOptions.port = 80;
+ }
+ req = http.request(requestOptions);
+ }
+
+ req.setHeader('connection', 'keep-alive');
+ req.setHeader('accept', 'application/json');
+
+ Object.keys(opts.headers).forEach(function setRequestHeader(headerName) {
+ req.setHeader(headerName, opts.headers[headerName]);
+ });
+
+ req.setHeader('accept-encoding', 'gzip,deflate');
+
+ // we do not use req.setTimeout because it's either an inactivity timeout
+ // or a global timeout given the nodejs version
+ timeoutId = setTimeout(timeout, opts.timeouts.connect);
+
+ req.once('error', error);
+ req.once('response', response);
+ if (body) {
+ req.setHeader('content-type', 'application/json');
+ req.setHeader('content-length', Buffer.byteLength(body, 'utf8'));
+ req.write(body);
+ } else if (req.method === 'DELETE') {
+ // Node.js was setting transfer-encoding: chunked on all DELETE requests
+ // which is not good since there's no body to be sent, resulting in nginx
+ // sending 400 on socket reuse (waiting for previous socket data)
+ // https://github.com/nodejs/node-v0.x-archive/issues/6164
+ // https://github.com/nodejs/node-v0.x-archive/commit/aef0960
+ req.setHeader('content-length', 0);
+ }
+
+ req.end();
+
+ function response(res) {
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(onCompleteTimeout, opts.timeouts.complete);
+ var chunks = [];
+ var originalRes = res;
+
+ // save headers and statusCode BEFORE treating the response as zlib, otherwise
+ // we lose them
+ var headers = res.headers;
+ var statusCode = res.statusCode;
+
+ // Algolia answers should be gzip when asked for it,
+ // but a proxy might uncompress Algolia response
+ // So we handle both compressed and uncompressed
+ if (headers['content-encoding'] === 'gzip' ||
+ headers['content-encoding'] === 'deflate') {
+ res = res.pipe(zlib.createUnzip());
+ }
+
+ res
+ .on('data', onData)
+ .once('error', reject)
+ .once('end', onEnd);
+
+ function onData(chunk) {
+ chunks.push(chunk);
+ }
+
+ function onEnd() {
+ clearTimeout(timeoutId);
+
+ var data = Buffer.concat(chunks).toString();
+ var out;
+
+ try {
+ out = {
+ body: JSON.parse(data),
+ responseText: data,
+ statusCode: statusCode,
+ headers: headers
+ };
+ } catch (e) {
+ out = new errors.UnparsableJSON({
+ more: data
+ });
+ }
+
+ if (out instanceof errors.UnparsableJSON) {
+ reject(out);
+ } else {
+ resolve(out);
+ }
+ }
+
+ function onCompleteTimeout() {
+ res.removeListener('data', onData);
+ res.removeListener('end', onEnd);
+ originalRes.destroy();
+ timeout();
+ }
+ }
+
+ function error(err) {
+ opts.debug('error: %j - %s', err, rawUrl);
+
+ if (timedOut) {
+ opts.debug('request had already timedout');
+ return;
+ }
+
+ abort();
+ clearTimeout(timeoutId);
+ reject(new errors.Network(err.message, err));
+ }
+
+ function timeout() {
+ timedOut = true;
+ opts.debug('timeout %s', rawUrl);
+ abort();
+ reject(new errors.RequestTimeout());
+ }
+
+ function abort() {
+ if (isNode010 && req.socket && req.socket.socket) {
+ req.socket.socket.destroy();
+ }
+
+ req.removeListener('response', response);
+ req.abort();
+ }
+ });
+};
+
+AlgoliaSearchNodeJS.prototype._promise = {
+ reject: function reject(val) {
+ return Promise.reject(val);
+ },
+ resolve: function resolve(val) {
+ return Promise.resolve(val);
+ },
+ delay: function delayPromise(ms) {
+ return new Promise(function resolveOnTimeout(resolve/* , reject */) {
+ setTimeout(resolve, ms);
+ });
+ },
+ all: function all(promises) {
+ return Promise.all(promises);
+ }
+};
+
+AlgoliaSearchNodeJS.prototype.destroy = function destroy() {
+ if (typeof this._Agent.destroy === 'function') {
+ this._Agent.destroy();
+ }
+};
+
+/*
+ * Generate a secured and public API Key from an apiKey and queryParameters
+ * optional user token identifying the current user
+ *
+ * @param apiKey - The api key to encode as secure
+ * @param {Object} [queryParameters] - Any search query parameter
+ */
+AlgoliaSearchNodeJS.prototype.generateSecuredApiKey = function generateSecuredApiKey(privateApiKey, queryParametersOrTagFilters, userToken) {
+ var searchParams;
+
+ if (Array.isArray(queryParametersOrTagFilters)) {
+ // generateSecuredApiKey(apiKey, ['user_42'], userToken);
+
+ searchParams = {
+ tagFilters: queryParametersOrTagFilters
+ };
+
+ if (userToken) {
+ searchParams.userToken = userToken;
+ }
+
+ searchParams = this._getSearchParams(searchParams, '');
+ } else if (typeof queryParametersOrTagFilters === 'string') {
+ if (queryParametersOrTagFilters.indexOf('=') === -1) {
+ // generateSecuredApiKey(apiKey, 'user_42', userToken);
+ searchParams = 'tagFilters=' + queryParametersOrTagFilters;
+ } else {
+ // generateSecuredApiKey(apiKey, 'tagFilters=user_42', userToken);
+ searchParams = queryParametersOrTagFilters;
+ }
+
+
+ if (userToken) {
+ searchParams += '&userToken=' + encodeURIComponent(userToken);
+ }
+ } else {
+ searchParams = this._getSearchParams(queryParametersOrTagFilters, '');
+ }
+
+ var securedKey = crypto
+ .createHmac('sha256', privateApiKey)
+ .update(searchParams)
+ .digest('hex');
+
+ return new Buffer(securedKey + searchParams).toString('base64');
+};