aws-embedded-metrics
Advanced tools
Comparing version 2.0.4 to 2.0.5
@@ -7,2 +7,3 @@ import { MetricsContext } from '../logger/MetricsContext'; | ||
private sink; | ||
private token; | ||
probe(): Promise<boolean>; | ||
@@ -9,0 +10,0 @@ getName(): string; |
@@ -30,3 +30,10 @@ "use strict"; | ||
const Logger_1 = require("../utils/Logger"); | ||
const endpoint = 'http://169.254.169.254/latest/dynamic/instance-identity/document'; | ||
// Documentation for configuring instance metadata can be found here: | ||
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html | ||
const host = '169.254.169.254'; | ||
const tokenPath = '/latest/api/token'; | ||
const tokenRequestHeaderKey = 'X-aws-ec2-metadata-token-ttl-seconds'; | ||
const tokenRequestHeaderValue = '21600'; | ||
const metadataPath = '/latest/dynamic/instance-identity/document'; | ||
const metadataRequestTokenHeaderKey = 'X-aws-ec2-metadata-token'; | ||
class EC2Environment { | ||
@@ -36,8 +43,24 @@ probe() { | ||
try { | ||
this.metadata = yield Fetch_1.fetch(endpoint); | ||
if (this.metadata) { | ||
return true; | ||
} | ||
const options = { | ||
host, | ||
path: tokenPath, | ||
method: "PUT", | ||
headers: { [tokenRequestHeaderKey]: tokenRequestHeaderValue } | ||
}; | ||
this.token = yield Fetch_1.fetchString(options); | ||
} | ||
catch (e) { | ||
Logger_1.LOG(e); | ||
return false; | ||
} | ||
try { | ||
const metadataOptions = { | ||
host, | ||
path: metadataPath, | ||
method: "GET", | ||
headers: { [metadataRequestTokenHeaderKey]: this.token } | ||
}; | ||
this.metadata = yield Fetch_1.fetchJSON(metadataOptions); | ||
return !!this.metadata; | ||
} | ||
catch (e) { | ||
@@ -44,0 +67,0 @@ Logger_1.LOG(e); |
@@ -53,3 +53,4 @@ "use strict"; | ||
try { | ||
this.metadata = yield Fetch_1.fetch(process.env.ECS_CONTAINER_METADATA_URI); | ||
const options = new URL(process.env.ECS_CONTAINER_METADATA_URI); | ||
this.metadata = yield Fetch_1.fetchJSON(options); | ||
if (this.metadata) { | ||
@@ -56,0 +57,0 @@ this.metadata.FormattedImageName = formatImageName(this.metadata.Image); |
@@ -0,3 +1,17 @@ | ||
/// <reference types="node" /> | ||
import { RequestOptions } from 'http'; | ||
/** | ||
* Fetch JSON data from an remote HTTP endpoint and de-serialize to the provided type. | ||
* Fetch data from a remote HTTP endpoint with the provided headers. | ||
* | ||
* @param options - HTTP request options | ||
*/ | ||
declare const fetch: (options: RequestOptions) => Promise<Buffer>; | ||
/** | ||
* Fetch a string from a remote HTTP endpoint with the provided headers. | ||
* | ||
* @param options - HTTP request options | ||
*/ | ||
declare const fetchString: (options: RequestOptions) => Promise<string>; | ||
/** | ||
* Fetch JSON data from a remote HTTP endpoint with the provided headers and de-serialize to the provided type. | ||
* There are no guarantees the response will conform to the contract defined by T. | ||
@@ -7,5 +21,5 @@ * It is up to the consumer to ensure the provided T captures all possible response types | ||
* | ||
* @param url - currently only supports HTTP | ||
* @param options - HTTP request options | ||
*/ | ||
declare const fetch: <T>(url: string) => Promise<T>; | ||
export { fetch }; | ||
declare const fetchJSON: <T>(options: RequestOptions) => Promise<T>; | ||
export { fetch, fetchJSON, fetchString }; |
@@ -16,19 +16,24 @@ "use strict"; | ||
*/ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http = require("http"); | ||
const http_1 = require("http"); | ||
const SOCKET_TIMEOUT = 1000; | ||
/** | ||
* Fetch JSON data from an remote HTTP endpoint and de-serialize to the provided type. | ||
* There are no guarantees the response will conform to the contract defined by T. | ||
* It is up to the consumer to ensure the provided T captures all possible response types | ||
* from the provided endpoint. | ||
* Fetch data from a remote HTTP endpoint with the provided headers. | ||
* | ||
* @param url - currently only supports HTTP | ||
* @param options - HTTP request options | ||
*/ | ||
const fetch = (url) => { | ||
const fetch = (options) => { | ||
return new Promise((resolve, reject) => { | ||
const request = http | ||
.get(url, { timeout: 2000 }, (response) => { | ||
const request = http_1.request(options, (response) => { | ||
if (!response.statusCode) { | ||
reject(`Received undefined response status code from '${url}'`); | ||
reject(`Received undefined response status code from '${options.host}${options.path}'`); | ||
return; | ||
@@ -49,12 +54,4 @@ } | ||
response.on('end', () => { | ||
let responseString; | ||
try { | ||
const buffer = Buffer.concat(body, bodyBytes); | ||
responseString = buffer.toString(); | ||
const parsedJson = JSON.parse(responseString); | ||
resolve(parsedJson); | ||
} | ||
catch (e) { | ||
reject(`Failed to parse response from '${url}' as JSON. Received: ${responseString}`); | ||
} | ||
const buffer = Buffer.concat(body, bodyBytes); | ||
resolve(buffer); | ||
}); | ||
@@ -68,8 +65,32 @@ }) | ||
request.abort(); | ||
reject(`Socket timeout while connecting to '${url}'`); | ||
reject(`Socket timeout while connecting to '${options.host}${options.path}'`); | ||
}); | ||
socket.setTimeout(SOCKET_TIMEOUT); | ||
}); | ||
request.end(); | ||
}); | ||
}; | ||
exports.fetch = fetch; | ||
/** | ||
* Fetch a string from a remote HTTP endpoint with the provided headers. | ||
* | ||
* @param options - HTTP request options | ||
*/ | ||
const fetchString = (options) => __awaiter(void 0, void 0, void 0, function* () { | ||
const buffer = yield fetch(options); | ||
return buffer.toString(); | ||
}); | ||
exports.fetchString = fetchString; | ||
/** | ||
* Fetch JSON data from a remote HTTP endpoint with the provided headers and de-serialize to the provided type. | ||
* There are no guarantees the response will conform to the contract defined by T. | ||
* It is up to the consumer to ensure the provided T captures all possible response types | ||
* from the provided endpoint. | ||
* | ||
* @param options - HTTP request options | ||
*/ | ||
const fetchJSON = (options) => __awaiter(void 0, void 0, void 0, function* () { | ||
const responseString = yield fetchString(options); | ||
return JSON.parse(responseString); | ||
}); | ||
exports.fetchJSON = fetchJSON; |
{ | ||
"name": "aws-embedded-metrics", | ||
"version": "2.0.4", | ||
"version": "2.0.5", | ||
"description": "AWS Embedded Metrics Client Library", | ||
@@ -36,3 +36,3 @@ "main": "lib/index.js", | ||
"@types/faker": "^4.1.5", | ||
"@types/jest": "^24.0.15", | ||
"@types/jest": "^26.0.22", | ||
"@types/node": "^12.0.8", | ||
@@ -46,8 +46,9 @@ "@typescript-eslint/eslint-plugin": "^2.23.0", | ||
"faker": "^4.1.0", | ||
"jest": "^24.8.0", | ||
"jest": "^26.6.3", | ||
"node-notifier": ">=8.0.1", | ||
"npm-pack-zip": "^1.2.7", | ||
"prettier": "^1.19.1", | ||
"ts-jest": "^26.1.1", | ||
"ts-jest": "^26.5.4", | ||
"typescript": "^3.8.0", | ||
"node-notifier": ">=8.0.1" | ||
"y18n": ">=4.0.1" | ||
}, | ||
@@ -57,3 +58,2 @@ "files": [ | ||
], | ||
"dependencies": {}, | ||
"volta": { | ||
@@ -60,0 +60,0 @@ "node": "10.16.0" |
116979
2275
17
5