Skip to content

Commit

Permalink
Add request id and user agent to client headers (openhab#737)
Browse files Browse the repository at this point in the history
Signed-off-by: jsetton <[email protected]>
  • Loading branch information
jsetton authored Dec 26, 2024
1 parent 1116f22 commit 84dc529
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 21 deletions.
6 changes: 3 additions & 3 deletions lambda/alexa/smarthome/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/

import { AxiosError } from 'axios';
import config from '#root/config.js';
import log from '#root/log.js';
import OpenHAB from '#openhab/index.js';
import AlexaDirective from './directive.js';
Expand All @@ -22,13 +21,14 @@ import { AlexaError, InvalidDirectiveError } from './errors.js';
/**
* Handles alexa smart home skill request
* @param {Object} request
* @param {Object} context
* @return {Promise}
*/
export const handleRequest = async (request) => {
export const handleRequest = async (request, context) => {
// Initialize directive object
const directive = new AlexaDirective(request.directive);
// Initialize openhab object
const openhab = new OpenHAB(config.openhab, directive.auth.token, AlexaResponse.TIMEOUT);
const openhab = new OpenHAB(context.awsRequestId, directive.auth.token, AlexaResponse.TIMEOUT);

let response;

Expand Down
5 changes: 3 additions & 2 deletions lambda/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ import { handleRequest } from './alexa/smarthome/index.js';
/**
* Defines skill event handler
* @param {Object} event
* @param {Object} context
* @return {Promise}
*/
export const handler = async (event) => {
export const handler = async (event, context) => {
log.info('Received event:', event);

if (event.directive?.header.payloadVersion === '3') {
return handleRequest(event);
return handleRequest(event, context);
}

log.warn('Unsupported event:', event);
Expand Down
16 changes: 11 additions & 5 deletions lambda/openhab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import fs from 'node:fs';
import axios from 'axios';
import { HttpsAgent } from 'agentkeepalive';
import { validate as uuidValidate } from 'uuid';
import config from '#root/config.js';
import { ItemType, ItemValue, UnitSymbol } from './constants.js';

const packageInfo = JSON.parse(fs.readFileSync('./package.json'));

/**
* Defines openHAB class
*/
Expand All @@ -30,12 +33,12 @@ export default class OpenHAB {

/**
* Constructor
* @param {Object} config
* @param {String} requestId
* @param {String} token
* @param {Number} timeout
*/
constructor(config, token, timeout) {
this._client = OpenHAB.createClient(config, token, timeout);
constructor(requestId, token, timeout) {
this._client = OpenHAB.createClient(config.openhab, requestId, token, timeout);
}

/**
Expand Down Expand Up @@ -205,16 +208,19 @@ export default class OpenHAB {
/**
* Returns request client
* @param {Object} config
* @param {String} requestId
* @param {String} token
* @param {Number} timeout
* @return {Object}
*/
static createClient(config, token, timeout) {
static createClient(config, requestId, token, timeout) {
const client = axios.create({
baseURL: config.baseURL,
headers: {
common: {
'Cache-Control': 'no-cache'
'Cache-Control': 'no-cache',
'User-Agent': `${packageInfo.name}/${packageInfo.version}`,
'X-Amzn-RequestId': requestId
}
},
httpsAgent: new HttpsAgent({
Expand Down
7 changes: 5 additions & 2 deletions lambda/test/alexa/smarthome.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ use(chaiCustom);

/* eslint-disable mocha/no-setup-in-describe */
describe('Alexa Smart Home Tests', function () {
// set default environment
const context = { awsRequestId: 'request-id' };

let commandStub, updateStub;

beforeEach(function () {
Expand Down Expand Up @@ -56,7 +59,7 @@ describe('Alexa Smart Home Tests', function () {
sinon.stub(OpenHAB.prototype, 'getAllItems').resolves(items);
sinon.stub(OpenHAB.prototype, 'getServerSettings').resolves(settings);
// run test
const response = await handleRequest({ directive });
const response = await handleRequest({ directive }, context);
expect(commandStub.called).to.be.false;
expect(updateStub.called).to.be.false;
expect(response)
Expand Down Expand Up @@ -86,7 +89,7 @@ describe('Alexa Smart Home Tests', function () {
sinon.stub(log, 'error');
}
// run test
const response = await handleRequest({ directive });
const response = await handleRequest({ directive }, context);
expect(commandStub.callCount).to.equal(expected.openhab.commands.length);
expect(commandStub.args.map(([name, value]) => ({ name, value }))).to.deep.equal(expected.openhab.commands);
expect(updateStub.callCount).to.equal(expected.openhab.updates.length);
Expand Down
35 changes: 29 additions & 6 deletions lambda/test/openhab.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,25 @@ import nock from 'nock';
import fs from 'node:fs';
import { AxiosError } from 'axios';
import { v4 as uuidv4 } from 'uuid';
import config from '#root/config.js';
import OpenHAB from '#openhab/index.js';

const packageInfo = JSON.parse(fs.readFileSync('./package.json'));

describe('OpenHAB Tests', function () {
// set default environment
const baseURL = 'https://foobar';
const requestId = 'request-id';
const token = 'token';
const timeout = 42;

let openhab;

beforeEach(function () {
// set stub environment
sinon.stub(config.openhab, 'baseURL').value(baseURL);
// create new openhab instance
openhab = new OpenHAB({ baseURL }, token, timeout);
openhab = new OpenHAB(requestId, token, timeout);
});

afterEach(function () {
Expand All @@ -43,20 +49,37 @@ describe('OpenHAB Tests', function () {
it('https oauth2 token', async function () {
// set environment
sinon.stub(fs, 'existsSync').returns(false);
nock(baseURL).get('/').matchHeader('Authorization', `Bearer ${token}`).reply(200);
nock(baseURL)
.get('/')
.matchHeader('Authorization', `Bearer ${token}`)
.reply(200)
.on('request', ({ headers }) => {
expect(headers).to.include({
authorization: `Bearer ${token}`,
'user-agent': `${packageInfo.name}/${packageInfo.version}`,
'x-amzn-requestid': requestId
});
});
// run test
await OpenHAB.createClient({ baseURL }, token, timeout).get('/');
await OpenHAB.createClient({ baseURL }, requestId, token, timeout).get('/');
expect(nock.isDone()).to.be.true;
});

it('https basic auth', async function () {
// set environment
const user = 'username';
const pass = 'password';
const token = Buffer.from(`${user}:${pass}`).toString('base64');
sinon.stub(fs, 'existsSync').returns(false);
nock(baseURL).get('/').basicAuth({ user, pass }).reply(200);
nock(baseURL)
.get('/')
.basicAuth({ user, pass })
.reply(200)
.on('request', ({ headers }) => {
expect(headers).to.include({ authorization: `Basic ${token}` });
});
// run test
await OpenHAB.createClient({ baseURL, user, pass }, token, timeout).get('/');
await OpenHAB.createClient({ baseURL, user, pass }, requestId, token, timeout).get('/');
expect(nock.isDone()).to.be.true;
});

Expand All @@ -76,7 +99,7 @@ describe('OpenHAB Tests', function () {
expect(socket).to.include({ timeout });
});
// run test
await OpenHAB.createClient({ baseURL, certFile, certPass }, token, timeout).get('/');
await OpenHAB.createClient({ baseURL, certFile, certPass }, requestId, token, timeout).get('/');
expect(nock.isDone()).to.be.true;
});

Expand Down
9 changes: 6 additions & 3 deletions lambda/test/skill.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import esmock from 'esmock';
import log from '#root/log.js';

describe('Skill Event Tests', function () {
// set default environment
const context = { awsRequestId: 'request-id' };

let smarthomeStub, skill;

beforeEach(async function () {
Expand Down Expand Up @@ -47,9 +50,9 @@ describe('Skill Event Tests', function () {
}
};
// run test
await skill.handler(event);
await skill.handler(event, context);
expect(smarthomeStub.called).to.be.true;
expect(smarthomeStub.firstCall.args).to.deep.equal([event]);
expect(smarthomeStub.firstCall.args).to.deep.equal([event, context]);
});

it('payload version 2', async function () {
Expand All @@ -63,7 +66,7 @@ describe('Skill Event Tests', function () {
};
const logWarn = sinon.stub(log, 'warn');
// run test
await skill.handler(event);
await skill.handler(event, context);
expect(smarthomeStub.called).to.be.false;
expect(logWarn.called).to.be.true;
expect(logWarn.firstCall.args).to.deep.equal(['Unsupported event:', event]);
Expand Down

0 comments on commit 84dc529

Please sign in to comment.