UNPKG

superagent

Version:

elegant & feature rich browser / node HTTP with a fluent API

181 lines (180 loc) • 21.2 kB
"use strict"; const http2 = require('http2'); const Stream = require('stream'); const net = require('net'); const tls = require('tls'); const { isSafeKey } = require('../utils'); const { HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS, HTTP2_HEADER_METHOD, HTTP2_HEADER_AUTHORITY, HTTP2_HEADER_HOST, HTTP2_HEADER_SET_COOKIE, NGHTTP2_CANCEL } = http2.constants; function setProtocol(protocol) { return { request(options) { return new Request(protocol, options); } }; } function normalizeIpv6Host(host) { return net.isIP(host) === 6 ? `[${host}]` : host; } class Request extends Stream { constructor(protocol, options) { super(); const defaultPort = protocol === 'https:' ? 443 : 80; const defaultHost = 'localhost'; const port = options.port || defaultPort; const host = options.host || defaultHost; delete options.port; delete options.host; this.method = options.method; this.path = options.path; this.protocol = protocol; this.host = host; delete options.method; delete options.path; const sessionOptions = { ...options }; if (options.socketPath) { sessionOptions.socketPath = options.socketPath; sessionOptions.createConnection = this.createUnixConnection.bind(this); } this._headers = {}; const normalizedHost = normalizeIpv6Host(host); const session = http2.connect(`${protocol}//${normalizedHost}:${port}`, sessionOptions); this.setHeader('host', `${normalizedHost}:${port}`); session.on('error', error => this.emit('error', error)); this.session = session; } createUnixConnection(authority, options) { switch (this.protocol) { case 'http:': return net.connect(options.socketPath); case 'https:': options.ALPNProtocols = ['h2']; options.servername = this.host; options.allowHalfOpen = true; return tls.connect(options.socketPath, options); default: throw new Error('Unsupported protocol', this.protocol); } } setNoDelay(bool) { // We can not use setNoDelay with HTTP/2. // Node 10 limits http2session.socket methods to ones safe to use with HTTP/2. // See also https://nodejs.org/api/http2.html#http2_http2session_socket } getFrame() { if (this.frame) { return this.frame; } const method = { [HTTP2_HEADER_PATH]: this.path, [HTTP2_HEADER_METHOD]: this.method }; let headers = this.mapToHttp2Header(this._headers); headers = Object.assign(headers, method); const frame = this.session.request(headers); frame.once('response', (headers, flags) => { headers = this.mapToHttpHeader(headers); frame.headers = headers; frame.statusCode = headers[HTTP2_HEADER_STATUS]; frame.status = frame.statusCode; this.emit('response', frame); }); this._headerSent = true; frame.on('drain', () => this.emit('drain')); frame.on('error', error => this.emit('error', error)); frame.on('close', () => this.session.close()); this.frame = frame; return frame; } mapToHttpHeader(headers) { const keys = Object.keys(headers); const http2Headers = {}; for (let key of keys) { let value = headers[key]; key = key.toLowerCase(); // header names come from the peer; never let one such as "__proto__" // reach into the prototype chain of the headers object if (!isSafeKey(key)) continue; switch (key) { case HTTP2_HEADER_SET_COOKIE: value = Array.isArray(value) ? value : [value]; break; default: break; } http2Headers[key] = value; } return http2Headers; } mapToHttp2Header(headers) { const keys = Object.keys(headers); const http2Headers = {}; for (let key of keys) { let value = headers[key]; key = key.toLowerCase(); switch (key) { case HTTP2_HEADER_HOST: key = HTTP2_HEADER_AUTHORITY; value = /^http:\/\/|^https:\/\//.test(value) ? new URL(value).host : value; break; default: break; } http2Headers[key] = value; } return http2Headers; } setHeader(name, value) { this._headers[name.toLowerCase()] = value; } getHeader(name) { return this._headers[name.toLowerCase()]; } write(data, encoding) { const frame = this.getFrame(); return frame.write(data, encoding); } pipe(stream, options) { const frame = this.getFrame(); return frame.pipe(stream, options); } end(data) { const frame = this.getFrame(); frame.end(data); } abort(data) { const frame = this.getFrame(); frame.close(NGHTTP2_CANCEL); this.session.destroy(); } _destroy(error, callback) { try { if (this.frame) { this.frame.close(NGHTTP2_CANCEL); } } catch (err) { // ignore } try { if (this.session && !this.session.destroyed) { this.session.destroy(); } } catch (err) { // ignore } callback(error); } } exports.setProtocol = setProtocol; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJodHRwMiIsInJlcXVpcmUiLCJTdHJlYW0iLCJuZXQiLCJ0bHMiLCJpc1NhZmVLZXkiLCJIVFRQMl9IRUFERVJfUEFUSCIsIkhUVFAyX0hFQURFUl9TVEFUVVMiLCJIVFRQMl9IRUFERVJfTUVUSE9EIiwiSFRUUDJfSEVBREVSX0FVVEhPUklUWSIsIkhUVFAyX0hFQURFUl9IT1NUIiwiSFRUUDJfSEVBREVSX1NFVF9DT09LSUUiLCJOR0hUVFAyX0NBTkNFTCIsImNvbnN0YW50cyIsInNldFByb3RvY29sIiwicHJvdG9jb2wiLCJyZXF1ZXN0Iiwib3B0aW9ucyIsIlJlcXVlc3QiLCJub3JtYWxpemVJcHY2SG9zdCIsImhvc3QiLCJpc0lQIiwiY29uc3RydWN0b3IiLCJkZWZhdWx0UG9ydCIsImRlZmF1bHRIb3N0IiwicG9ydCIsIm1ldGhvZCIsInBhdGgiLCJzZXNzaW9uT3B0aW9ucyIsInNvY2tldFBhdGgiLCJjcmVhdGVDb25uZWN0aW9uIiwiY3JlYXRlVW5peENvbm5lY3Rpb24iLCJiaW5kIiwiX2hlYWRlcnMiLCJub3JtYWxpemVkSG9zdCIsInNlc3Npb24iLCJjb25uZWN0Iiwic2V0SGVhZGVyIiwib24iLCJlcnJvciIsImVtaXQiLCJhdXRob3JpdHkiLCJBTFBOUHJvdG9jb2xzIiwic2VydmVybmFtZSIsImFsbG93SGFsZk9wZW4iLCJFcnJvciIsInNldE5vRGVsYXkiLCJib29sIiwiZ2V0RnJhbWUiLCJmcmFtZSIsImhlYWRlcnMiLCJtYXBUb0h0dHAySGVhZGVyIiwiT2JqZWN0IiwiYXNzaWduIiwib25jZSIsImZsYWdzIiwibWFwVG9IdHRwSGVhZGVyIiwic3RhdHVzQ29kZSIsInN0YXR1cyIsIl9oZWFkZXJTZW50IiwiY2xvc2UiLCJrZXlzIiwiaHR0cDJIZWFkZXJzIiwia2V5IiwidmFsdWUiLCJ0b0xvd2VyQ2FzZSIsIkFycmF5IiwiaXNBcnJheSIsInRlc3QiLCJVUkwiLCJuYW1lIiwiZ2V0SGVhZGVyIiwid3JpdGUiLCJkYXRhIiwiZW5jb2RpbmciLCJwaXBlIiwic3RyZWFtIiwiZW5kIiwiYWJvcnQiLCJkZXN0cm95IiwiX2Rlc3Ryb3kiLCJjYWxsYmFjayIsImVyciIsImRlc3Ryb3llZCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbm9kZS9odHRwMndyYXBwZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgaHR0cDIgPSByZXF1aXJlKCdodHRwMicpO1xuY29uc3QgU3RyZWFtID0gcmVxdWlyZSgnc3RyZWFtJyk7XG5jb25zdCBuZXQgPSByZXF1aXJlKCduZXQnKTtcbmNvbnN0IHRscyA9IHJlcXVpcmUoJ3RscycpO1xuY29uc3QgeyBpc1NhZmVLZXkgfSA9IHJlcXVpcmUoJy4uL3V0aWxzJyk7XG5cbmNvbnN0IHtcbiAgSFRUUDJfSEVBREVSX1BBVEgsXG4gIEhUVFAyX0hFQURFUl9TVEFUVVMsXG4gIEhUVFAyX0hFQURFUl9NRVRIT0QsXG4gIEhUVFAyX0hFQURFUl9BVVRIT1JJVFksXG4gIEhUVFAyX0hFQURFUl9IT1NULFxuICBIVFRQMl9IRUFERVJfU0VUX0NPT0tJRSxcbiAgTkdIVFRQMl9DQU5DRUxcbn0gPSBodHRwMi5jb25zdGFudHM7XG5cbmZ1bmN0aW9uIHNldFByb3RvY29sKHByb3RvY29sKSB7XG4gIHJldHVybiB7XG4gICAgcmVxdWVzdChvcHRpb25zKSB7XG4gICAgICByZXR1cm4gbmV3IFJlcXVlc3QocHJvdG9jb2wsIG9wdGlvbnMpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplSXB2Nkhvc3QoaG9zdCkge1xuICByZXR1cm4gbmV0LmlzSVAoaG9zdCkgPT09IDYgPyBgWyR7aG9zdH1dYCA6IGhvc3Q7XG59XG5cbmNsYXNzIFJlcXVlc3QgZXh0ZW5kcyBTdHJlYW0ge1xuICBjb25zdHJ1Y3Rvcihwcm90b2NvbCwgb3B0aW9ucykge1xuICAgIHN1cGVyKCk7XG4gICAgY29uc3QgZGVmYXVsdFBvcnQgPSBwcm90b2NvbCA9PT0gJ2h0dHBzOicgPyA0NDMgOiA4MDtcbiAgICBjb25zdCBkZWZhdWx0SG9zdCA9ICdsb2NhbGhvc3QnO1xuICAgIGNvbnN0IHBvcnQgPSBvcHRpb25zLnBvcnQgfHwgZGVmYXVsdFBvcnQ7XG4gICAgY29uc3QgaG9zdCA9IG9wdGlvbnMuaG9zdCB8fCBkZWZhdWx0SG9zdDtcblxuICAgIGRlbGV0ZSBvcHRpb25zLnBvcnQ7XG4gICAgZGVsZXRlIG9wdGlvbnMuaG9zdDtcblxuICAgIHRoaXMubWV0aG9kID0gb3B0aW9ucy5tZXRob2Q7XG4gICAgdGhpcy5wYXRoID0gb3B0aW9ucy5wYXRoO1xuICAgIHRoaXMucHJvdG9jb2wgPSBwcm90b2NvbDtcbiAgICB0aGlzLmhvc3QgPSBob3N0O1xuXG4gICAgZGVsZXRlIG9wdGlvbnMubWV0aG9kO1xuICAgIGRlbGV0ZSBvcHRpb25zLnBhdGg7XG5cbiAgICBjb25zdCBzZXNzaW9uT3B0aW9ucyA9IHsgLi4ub3B0aW9ucyB9O1xuICAgIGlmIChvcHRpb25zLnNvY2tldFBhdGgpIHtcbiAgICAgIHNlc3Npb25PcHRpb25zLnNvY2tldFBhdGggPSBvcHRpb25zLnNvY2tldFBhdGg7XG4gICAgICBzZXNzaW9uT3B0aW9ucy5jcmVhdGVDb25uZWN0aW9uID0gdGhpcy5jcmVhdGVVbml4Q29ubmVjdGlvbi5iaW5kKHRoaXMpO1xuICAgIH1cblxuICAgIHRoaXMuX2hlYWRlcnMgPSB7fTtcblxuICAgIGNvbnN0IG5vcm1hbGl6ZWRIb3N0ID0gbm9ybWFsaXplSXB2Nkhvc3QoaG9zdCk7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IGh0dHAyLmNvbm5lY3QoXG4gICAgICBgJHtwcm90b2NvbH0vLyR7bm9ybWFsaXplZEhvc3R9OiR7cG9ydH1gLFxuICAgICAgc2Vzc2lvbk9wdGlvbnNcbiAgICApO1xuICAgIHRoaXMuc2V0SGVhZGVyKCdob3N0JywgYCR7bm9ybWFsaXplZEhvc3R9OiR7cG9ydH1gKTtcblxuICAgIHNlc3Npb24ub24oJ2Vycm9yJywgKGVycm9yKSA9PiB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyb3IpKTtcblxuICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG4gIH1cblxuICBjcmVhdGVVbml4Q29ubmVjdGlvbihhdXRob3JpdHksIG9wdGlvbnMpIHtcbiAgICBzd2l0Y2ggKHRoaXMucHJvdG9jb2wpIHtcbiAgICAgIGNhc2UgJ2h0dHA6JzpcbiAgICAgICAgcmV0dXJuIG5ldC5jb25uZWN0KG9wdGlvbnMuc29ja2V0UGF0aCk7XG4gICAgICBjYXNlICdodHRwczonOlxuICAgICAgICBvcHRpb25zLkFMUE5Qcm90b2NvbHMgPSBbJ2gyJ107XG4gICAgICAgIG9wdGlvbnMuc2VydmVybmFtZSA9IHRoaXMuaG9zdDtcbiAgICAgICAgb3B0aW9ucy5hbGxvd0hhbGZPcGVuID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRscy5jb25uZWN0KG9wdGlvbnMuc29ja2V0UGF0aCwgb3B0aW9ucyk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIHByb3RvY29sJywgdGhpcy5wcm90b2NvbCk7XG4gICAgfVxuICB9XG5cbiAgc2V0Tm9EZWxheShib29sKSB7XG4gICAgLy8gV2UgY2FuIG5vdCB1c2Ugc2V0Tm9EZWxheSB3aXRoIEhUVFAvMi5cbiAgICAvLyBOb2RlIDEwIGxpbWl0cyBodHRwMnNlc3Npb24uc29ja2V0IG1ldGhvZHMgdG8gb25lcyBzYWZlIHRvIHVzZSB3aXRoIEhUVFAvMi5cbiAgICAvLyBTZWUgYWxzbyBodHRwczovL25vZGVqcy5vcmcvYXBpL2h0dHAyLmh0bWwjaHR0cDJfaHR0cDJzZXNzaW9uX3NvY2tldFxuICB9XG5cbiAgZ2V0RnJhbWUoKSB7XG4gICAgaWYgKHRoaXMuZnJhbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmZyYW1lO1xuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9IHtcbiAgICAgIFtIVFRQMl9IRUFERVJfUEFUSF06IHRoaXMucGF0aCxcbiAgICAgIFtIVFRQMl9IRUFERVJfTUVUSE9EXTogdGhpcy5tZXRob2RcbiAgICB9O1xuXG4gICAgbGV0IGhlYWRlcnMgPSB0aGlzLm1hcFRvSHR0cDJIZWFkZXIodGhpcy5faGVhZGVycyk7XG5cbiAgICBoZWFkZXJzID0gT2JqZWN0LmFzc2lnbihoZWFkZXJzLCBtZXRob2QpO1xuXG4gICAgY29uc3QgZnJhbWUgPSB0aGlzLnNlc3Npb24ucmVxdWVzdChoZWFkZXJzKTtcblxuICAgIGZyYW1lLm9uY2UoJ3Jlc3BvbnNlJywgKGhlYWRlcnMsIGZsYWdzKSA9PiB7XG4gICAgICBoZWFkZXJzID0gdGhpcy5tYXBUb0h0dHBIZWFkZXIoaGVhZGVycyk7XG4gICAgICBmcmFtZS5oZWFkZXJzID0gaGVhZGVycztcbiAgICAgIGZyYW1lLnN0YXR1c0NvZGUgPSBoZWFkZXJzW0hUVFAyX0hFQURFUl9TVEFUVVNdO1xuICAgICAgZnJhbWUuc3RhdHVzID0gZnJhbWUuc3RhdHVzQ29kZTtcbiAgICAgIHRoaXMuZW1pdCgncmVzcG9uc2UnLCBmcmFtZSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLl9oZWFkZXJTZW50ID0gdHJ1ZTtcblxuICAgIGZyYW1lLm9uKCdkcmFpbicsICgpID0+IHRoaXMuZW1pdCgnZHJhaW4nKSk7XG4gICAgZnJhbWUub24oJ2Vycm9yJywgKGVycm9yKSA9PiB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyb3IpKTtcbiAgICBmcmFtZS5vbignY2xvc2UnLCAoKSA9PiB0aGlzLnNlc3Npb24uY2xvc2UoKSk7XG5cbiAgICB0aGlzLmZyYW1lID0gZnJhbWU7XG4gICAgcmV0dXJuIGZyYW1lO1xuICB9XG5cbiAgbWFwVG9IdHRwSGVhZGVyKGhlYWRlcnMpIHtcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoaGVhZGVycyk7XG4gICAgY29uc3QgaHR0cDJIZWFkZXJzID0ge307XG4gICAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICAgIGxldCB2YWx1ZSA9IGhlYWRlcnNba2V5XTtcbiAgICAgIGtleSA9IGtleS50b0xvd2VyQ2FzZSgpO1xuICAgICAgLy8gaGVhZGVyIG5hbWVzIGNvbWUgZnJvbSB0aGUgcGVlcjsgbmV2ZXIgbGV0IG9uZSBzdWNoIGFzIFwiX19wcm90b19fXCJcbiAgICAgIC8vIHJlYWNoIGludG8gdGhlIHByb3RvdHlwZSBjaGFpbiBvZiB0aGUgaGVhZGVycyBvYmplY3RcbiAgICAgIGlmICghaXNTYWZlS2V5KGtleSkpIGNvbnRpbnVlO1xuICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSBIVFRQMl9IRUFERVJfU0VUX0NPT0tJRTpcbiAgICAgICAgICB2YWx1ZSA9IEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBodHRwMkhlYWRlcnNba2V5XSA9IHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBodHRwMkhlYWRlcnM7XG4gIH1cblxuICBtYXBUb0h0dHAySGVhZGVyKGhlYWRlcnMpIHtcbiAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoaGVhZGVycyk7XG4gICAgY29uc3QgaHR0cDJIZWFkZXJzID0ge307XG4gICAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICAgIGxldCB2YWx1ZSA9IGhlYWRlcnNba2V5XTtcbiAgICAgIGtleSA9IGtleS50b0xvd2VyQ2FzZSgpO1xuICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSBIVFRQMl9IRUFERVJfSE9TVDpcbiAgICAgICAgICBrZXkgPSBIVFRQMl9IRUFERVJfQVVUSE9SSVRZO1xuICAgICAgICAgIHZhbHVlID0gL15odHRwOlxcL1xcL3xeaHR0cHM6XFwvXFwvLy50ZXN0KHZhbHVlKVxuICAgICAgICAgICAgPyBuZXcgVVJMKHZhbHVlKS5ob3N0XG4gICAgICAgICAgICA6IHZhbHVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBodHRwMkhlYWRlcnNba2V5XSA9IHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBodHRwMkhlYWRlcnM7XG4gIH1cblxuICBzZXRIZWFkZXIobmFtZSwgdmFsdWUpIHtcbiAgICB0aGlzLl9oZWFkZXJzW25hbWUudG9Mb3dlckNhc2UoKV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldEhlYWRlcihuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuX2hlYWRlcnNbbmFtZS50b0xvd2VyQ2FzZSgpXTtcbiAgfVxuXG4gIHdyaXRlKGRhdGEsIGVuY29kaW5nKSB7XG4gICAgY29uc3QgZnJhbWUgPSB0aGlzLmdldEZyYW1lKCk7XG4gICAgcmV0dXJuIGZyYW1lLndyaXRlKGRhdGEsIGVuY29kaW5nKTtcbiAgfVxuXG4gIHBpcGUoc3RyZWFtLCBvcHRpb25zKSB7XG4gICAgY29uc3QgZnJhbWUgPSB0aGlzLmdldEZyYW1lKCk7XG4gICAgcmV0dXJuIGZyYW1lLnBpcGUoc3RyZWFtLCBvcHRpb25zKTtcbiAgfVxuXG4gIGVuZChkYXRhKSB7XG4gICAgY29uc3QgZnJhbWUgPSB0aGlzLmdldEZyYW1lKCk7XG4gICAgZnJhbWUuZW5kKGRhdGEpO1xuICB9XG5cbiAgYWJvcnQoZGF0YSkge1xuICAgIGNvbnN0IGZyYW1lID0gdGhpcy5nZXRGcmFtZSgpO1xuICAgIGZyYW1lLmNsb3NlKE5HSFRUUDJfQ0FOQ0VMKTtcbiAgICB0aGlzLnNlc3Npb24uZGVzdHJveSgpO1xuICB9XG5cbiAgX2Rlc3Ryb3koZXJyb3IsIGNhbGxiYWNrKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLmZyYW1lKSB7XG4gICAgICAgIHRoaXMuZnJhbWUuY2xvc2UoTkdIVFRQMl9DQU5DRUwpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgLy8gaWdub3JlXG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLnNlc3Npb24gJiYgIXRoaXMuc2Vzc2lvbi5kZXN0cm95ZWQpIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIGlnbm9yZVxuICAgIH1cblxuICAgIGNhbGxiYWNrKGVycm9yKTtcbiAgfVxufVxuXG5leHBvcnRzLnNldFByb3RvY29sID0gc2V0UHJvdG9jb2w7XG4iXSwibWFwcGluZ3MiOiI7O0FBQUEsTUFBTUEsS0FBSyxHQUFHQyxPQUFPLENBQUMsT0FBTyxDQUFDO0FBQzlCLE1BQU1DLE1BQU0sR0FBR0QsT0FBTyxDQUFDLFFBQVEsQ0FBQztBQUNoQyxNQUFNRSxHQUFHLEdBQUdGLE9BQU8sQ0FBQyxLQUFLLENBQUM7QUFDMUIsTUFBTUcsR0FBRyxHQUFHSCxPQUFPLENBQUMsS0FBSyxDQUFDO0FBQzFCLE1BQU07RUFBRUk7QUFBVSxDQUFDLEdBQUdKLE9BQU8sQ0FBQyxVQUFVLENBQUM7QUFFekMsTUFBTTtFQUNKSyxpQkFBaUI7RUFDakJDLG1CQUFtQjtFQUNuQkMsbUJBQW1CO0VBQ25CQyxzQkFBc0I7RUFDdEJDLGlCQUFpQjtFQUNqQkMsdUJBQXVCO0VBQ3ZCQztBQUNGLENBQUMsR0FBR1osS0FBSyxDQUFDYSxTQUFTO0FBRW5CLFNBQVNDLFdBQVdBLENBQUNDLFFBQVEsRUFBRTtFQUM3QixPQUFPO0lBQ0xDLE9BQU9BLENBQUNDLE9BQU8sRUFBRTtNQUNmLE9BQU8sSUFBSUMsT0FBTyxDQUFDSCxRQUFRLEVBQUVFLE9BQU8sQ0FBQztJQUN2QztFQUNGLENBQUM7QUFDSDtBQUVBLFNBQVNFLGlCQUFpQkEsQ0FBQ0MsSUFBSSxFQUFFO0VBQy9CLE9BQU9qQixHQUFHLENBQUNrQixJQUFJLENBQUNELElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJQSxJQUFJLEdBQUcsR0FBR0EsSUFBSTtBQUNsRDtBQUVBLE1BQU1GLE9BQU8sU0FBU2hCLE1BQU0sQ0FBQztFQUMzQm9CLFdBQVdBLENBQUNQLFFBQVEsRUFBRUUsT0FBTyxFQUFFO0lBQzdCLEtBQUssQ0FBQyxDQUFDO0lBQ1AsTUFBTU0sV0FBVyxH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