More cleanup
This commit is contained in:
parent
423be484b2
commit
dabdfc56a5
@ -1,3 +1,5 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The contents in this file were taken from NorthernMan54/Hap-Node-Client
|
* The contents in this file were taken from NorthernMan54/Hap-Node-Client
|
||||||
* https://raw.githubusercontent.com/NorthernMan54/Hap-Node-Client/master/lib/httpParser.js
|
* https://raw.githubusercontent.com/NorthernMan54/Hap-Node-Client/master/lib/httpParser.js
|
||||||
@ -16,26 +18,21 @@ interface IHttpResult {
|
|||||||
method?: string;
|
method?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
headers?: Dictionary<string | number>;
|
headers?: Dictionary<string | number>;
|
||||||
//eslint-disable-next-line
|
|
||||||
body?: any;
|
body?: any;
|
||||||
//eslint-disable-next-line
|
|
||||||
boundary?: any;
|
boundary?: any;
|
||||||
//eslint-disable-next-line
|
|
||||||
multipart?: any;
|
multipart?: any;
|
||||||
//eslint-disable-next-line
|
|
||||||
additional?: any;
|
additional?: any;
|
||||||
//eslint-disable-next-line
|
|
||||||
meta?: any;
|
meta?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class HttpMessageParser {
|
export default class HttpMessageParser {
|
||||||
private static requestLineRegex = /(HTTP|EVENT)\/(1\.0|1\.1|2\.0)\s+(\d+)\s+([\w\s-_]+)/i;
|
private requestLineRegex = /(HTTP|EVENT)\/(1\.0|1\.1|2\.0)\s+(\d+)\s+([\w\s-_]+)/i;
|
||||||
private static responseLineRegex = /(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|TRACE|CONNECT)\s+(.*)\s+HTTP\/(1\.0|1\.1|2\.0)/i;
|
private responseLineRegex = /(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|TRACE|CONNECT)\s+(.*)\s+HTTP\/(1\.0|1\.1|2\.0)/i;
|
||||||
private static headerNewlineRegex = /^[\r\n]+/gim;
|
private headerNewlineRegex = /^[\r\n]+/gim;
|
||||||
private static boundaryRegex = /(\n|\r\n)+--[\w-]+(\n|\r\n)+/g;
|
private boundaryRegex = /(\n|\r\n)+--[\w-]+(\n|\r\n)+/g;
|
||||||
|
|
||||||
//eslint-disable-next-line
|
//eslint-disable-next-line
|
||||||
public static parse(message: any): IHttpResult {
|
public parse(message: any): IHttpResult {
|
||||||
const result: IHttpResult = {};
|
const result: IHttpResult = {};
|
||||||
|
|
||||||
let messageString = '';
|
let messageString = '';
|
||||||
@ -119,7 +116,11 @@ export default class HttpMessageParser {
|
|||||||
/* Parse body
|
/* Parse body
|
||||||
*/
|
*/
|
||||||
let start = headerNewlineIndex;
|
let start = headerNewlineIndex;
|
||||||
const contentLength: number = result.headers!['Content-Length'] as number;
|
|
||||||
|
let contentLength = 0;
|
||||||
|
if (result.headers) {
|
||||||
|
contentLength = result.headers['Content-Length'] as number;
|
||||||
|
}
|
||||||
|
|
||||||
let end = (result.headers && result.headers['Content-Length'] && contentLength ? contentLength + start : messageString.length);
|
let end = (result.headers && result.headers['Content-Length'] && contentLength ? contentLength + start : messageString.length);
|
||||||
|
|
||||||
@ -163,7 +164,7 @@ export default class HttpMessageParser {
|
|||||||
const splitRegex = new RegExp('^' + fullBoundary + '.*[\n\r]?$', 'gm');
|
const splitRegex = new RegExp('^' + fullBoundary + '.*[\n\r]?$', 'gm');
|
||||||
const parts = multipartBody.split(splitRegex);
|
const parts = multipartBody.split(splitRegex);
|
||||||
|
|
||||||
result.multipart = parts.filter(this.isTruthy).map(function (part, i) {
|
result.multipart = parts.filter(this.isTruthy).map((part, index) => {
|
||||||
// tslint:disable-next-line: no-shadowed-variable
|
// tslint:disable-next-line: no-shadowed-variable
|
||||||
const result: IHttpResult = {};
|
const result: IHttpResult = {};
|
||||||
|
|
||||||
@ -188,7 +189,7 @@ export default class HttpMessageParser {
|
|||||||
let endOffset = null;
|
let endOffset = null;
|
||||||
|
|
||||||
if (newlineIndex > -1) {
|
if (newlineIndex > -1) {
|
||||||
const headers = HttpMessageParser.parseHeaders(possibleHeadersString);
|
const headers = this.parseHeaders(possibleHeadersString);
|
||||||
if (Object.keys(headers).length > 0) {
|
if (Object.keys(headers).length > 0) {
|
||||||
result.headers = headers;
|
result.headers = headers;
|
||||||
|
|
||||||
@ -211,8 +212,8 @@ export default class HttpMessageParser {
|
|||||||
boundaryNewlineIndexes.push(headerNewlineIndex);
|
boundaryNewlineIndexes.push(headerNewlineIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
startOffset = boundaryNewlineIndexes[i];
|
startOffset = boundaryNewlineIndexes[index];
|
||||||
endOffset = boundaryIndexes[i + 1];
|
endOffset = boundaryIndexes[index + 1];
|
||||||
body = message.slice(startOffset, endOffset);
|
body = message.slice(startOffset, endOffset);
|
||||||
} else {
|
} else {
|
||||||
body = part;
|
body = part;
|
||||||
@ -233,7 +234,7 @@ export default class HttpMessageParser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static trim(str: string): string {
|
private trim(str: string): string {
|
||||||
const firstNonWhitespaceRegex = /[\w-]+/gim;
|
const firstNonWhitespaceRegex = /[\w-]+/gim;
|
||||||
const firstNonWhitespaceIndex = str.search(firstNonWhitespaceRegex);
|
const firstNonWhitespaceIndex = str.search(firstNonWhitespaceRegex);
|
||||||
let tmpStr = "";
|
let tmpStr = "";
|
||||||
@ -245,11 +246,11 @@ export default class HttpMessageParser {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static isTruthy = function _isTruthy(value: any): boolean {
|
private isTruthy = function _isTruthy(value: any): boolean {
|
||||||
return !!value;
|
return !!value;
|
||||||
};
|
};
|
||||||
|
|
||||||
private static isNumeric = function _isNumeric(value: any): boolean {
|
private isNumeric = function _isNumeric(value: any): boolean {
|
||||||
if (typeof value === 'number' && !isNaN(value)) {
|
if (typeof value === 'number' && !isNaN(value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -263,35 +264,35 @@ export default class HttpMessageParser {
|
|||||||
return !isNaN(value);
|
return !isNaN(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
private static isBuffer = (item: any): boolean => {
|
private isBuffer = (item: any): boolean => {
|
||||||
return ((HttpMessageParser.isNodeBufferSupported() &&
|
return ((this.isNodeBufferSupported() &&
|
||||||
typeof global === 'object' &&
|
typeof global === 'object' &&
|
||||||
global.Buffer.isBuffer(item)) ||
|
global.Buffer.isBuffer(item)) ||
|
||||||
(item instanceof Object &&
|
(item instanceof Object &&
|
||||||
item._isBuffer));
|
item._isBuffer));
|
||||||
};
|
};
|
||||||
|
|
||||||
private static isNodeBufferSupported = (): boolean => {
|
private isNodeBufferSupported = (): boolean => {
|
||||||
return (typeof global === 'object' &&
|
return (typeof global === 'object' &&
|
||||||
typeof global.Buffer === 'function' &&
|
typeof global.Buffer === 'function' &&
|
||||||
typeof global.Buffer.isBuffer === 'function');
|
typeof global.Buffer.isBuffer === 'function');
|
||||||
};
|
};
|
||||||
|
|
||||||
private static parseHeaders = (body: any): Dictionary<string | number> => {
|
private parseHeaders = (body: any): Dictionary<string | number> => {
|
||||||
const headers: Dictionary<string | number> = {};
|
const headers: Dictionary<string | number> = {};
|
||||||
|
|
||||||
if (typeof body !== 'string') {
|
if (typeof body !== 'string') {
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.split(/[\r\n]/).forEach(function (string) {
|
body.split(/[\r\n]/).forEach((str: string) => {
|
||||||
const match = string.match(/([\w-]+):\s*(.*)/i);
|
const match = str.match(/([\w-]+):\s*(.*)/i);
|
||||||
|
|
||||||
if (Array.isArray(match) && match.length === 3) {
|
if (Array.isArray(match) && match.length === 3) {
|
||||||
const key = match[1];
|
const key = match[1];
|
||||||
const value = match[2];
|
const value = match[2];
|
||||||
|
|
||||||
headers[key] = HttpMessageParser.isNumeric(value) ? Number(value) : value;
|
headers[key] = this.isNumeric(value) ? Number(value) : value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
import * as net from 'net';
|
import * as net from 'net';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import HttpMessageParser from './httpParser';
|
|
||||||
import { Dictionary } from '../../Types/types';
|
import { Dictionary } from '../../Types/types';
|
||||||
|
import HttpMessageParser from './httpParser';
|
||||||
|
|
||||||
interface IRequest {
|
interface IRequest {
|
||||||
method: 'PUT' | 'POST' | 'GET' | 'DELETE' | 'PATCH';
|
method: 'PUT' | 'POST' | 'GET' | 'DELETE' | 'PATCH';
|
||||||
@ -16,7 +16,6 @@ interface IRequest {
|
|||||||
body: string;
|
body: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const parseMessage = HttpMessageParser.parse;
|
|
||||||
|
|
||||||
function _headersToString(headers: Dictionary<string>): string {
|
function _headersToString(headers: Dictionary<string>): string {
|
||||||
let response = '';
|
let response = '';
|
||||||
@ -71,3 +70,5 @@ export function createConnection(instance: { ipAddress: string; port: number },
|
|||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { HttpMessageParser };
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { IServiceType, IHapEvInstance } from './interfaces';
|
import { IServiceType, IHapEvInstance } from './interfaces';
|
||||||
import { createConnection, parseMessage } from './eventedHttpClient';
|
import { createConnection, HttpMessageParser } from './eventedHttpClient';
|
||||||
import { CharacteristicType } from './hapClient';
|
import { CharacteristicType } from './hapClient';
|
||||||
import { log } from '../Types/types';
|
import { log } from '../Types/types';
|
||||||
|
|
||||||
@ -10,6 +10,7 @@ export class HapMonitor extends EventEmitter {
|
|||||||
private services: IServiceType[];
|
private services: IServiceType[];
|
||||||
private logger: log;
|
private logger: log;
|
||||||
private debug: log;
|
private debug: log;
|
||||||
|
private parser: HttpMessageParser
|
||||||
|
|
||||||
constructor(logger: log, debug: log, pin: string, services: IServiceType[]) {
|
constructor(logger: log, debug: log, pin: string, services: IServiceType[]) {
|
||||||
super();
|
super();
|
||||||
@ -18,6 +19,7 @@ export class HapMonitor extends EventEmitter {
|
|||||||
this.pin = pin;
|
this.pin = pin;
|
||||||
this.services = services;
|
this.services = services;
|
||||||
this.evInstances = [];
|
this.evInstances = [];
|
||||||
|
this.parser = new HttpMessageParser();
|
||||||
|
|
||||||
// get a list of characteristics we can watch for each instance
|
// get a list of characteristics we can watch for each instance
|
||||||
this.parseServices();
|
this.parseServices();
|
||||||
@ -36,7 +38,7 @@ export class HapMonitor extends EventEmitter {
|
|||||||
this.debug(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] Connected`);
|
this.debug(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] Connected`);
|
||||||
|
|
||||||
instance.socket.on('data', (data) => {
|
instance.socket.on('data', (data) => {
|
||||||
const message = parseMessage(data);
|
const message = this.parser.parse(data);
|
||||||
|
|
||||||
|
|
||||||
if (message.statusCode === 401) {
|
if (message.statusCode === 401) {
|
||||||
|
5
src/HapClient/index.ts
Normal file
5
src/HapClient/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { HapClient } from './hapClient';
|
||||||
|
import { HapMonitor } from './hapMonitor';
|
||||||
|
|
||||||
|
export { HapClient };
|
||||||
|
export { HapMonitor };
|
@ -1,7 +1,7 @@
|
|||||||
import { Socket } from 'net';
|
import { Socket } from 'net';
|
||||||
|
|
||||||
export interface IHapInstance {
|
export interface IHapInstance {
|
||||||
displayName: string
|
displayName: string;
|
||||||
name: string;
|
name: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
port: number;
|
port: number;
|
||||||
@ -13,7 +13,7 @@ export interface IHapEvInstance {
|
|||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
port: number;
|
port: number;
|
||||||
username: string;
|
username: string;
|
||||||
evCharacteristics?: { aid: number, iid: number, ev: boolean }[];
|
evCharacteristics?: { aid: number; iid: number; ev: boolean }[];
|
||||||
socket?: Socket;
|
socket?: Socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ export interface IServiceResp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IAccessoryResp {
|
export interface IAccessoryResp {
|
||||||
instance: IInstanceResp
|
instance: IInstanceResp;
|
||||||
aid: number;
|
aid: number;
|
||||||
services: Array<IServiceResp>;
|
services: Array<IServiceResp>;
|
||||||
}
|
}
|
||||||
@ -121,4 +121,4 @@ export const createDefaultCharacteristicType = (): ICharacteristicType => {
|
|||||||
canWrite: false,
|
canWrite: false,
|
||||||
ev: false,
|
ev: false,
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to convert callbacks into promises
|
* Helper function to convert callbacks into promises
|
||||||
* @param func
|
* @param func
|
||||||
*/
|
*/
|
||||||
export default function callbackify(func: (...args: any[]) => Promise<any>): Function {
|
export default function callbackify(func: (...args: any[]) => Promise<any>): Function {
|
||||||
return (...args: any[]) => {
|
return (...args: any[]): void => {
|
||||||
const onlyArgs: any[] = [];
|
const onlyArgs: any[] = [];
|
||||||
let maybeCallback: Function | null = null;
|
let maybeCallback: Function | null = null;
|
||||||
|
|
||||||
@ -25,6 +26,6 @@ export default function callbackify(func: (...args: any[]) => Promise<any>): Fun
|
|||||||
|
|
||||||
func(...onlyArgs)
|
func(...onlyArgs)
|
||||||
.then((data: any) => callback(null, data))
|
.then((data: any) => callback(null, data))
|
||||||
.catch((err: any) => callback(err))
|
.catch((err: any) => callback(err));
|
||||||
}
|
};
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
export function sleep(ms: number) {
|
export function sleep(ms: number): Promise<number> {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise((resolve): number => setTimeout(resolve, ms));
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { HapClient } from "../HapClient/hapClient";
|
import { HapClient } from "../HapClient";
|
||||||
import { log } from '../Types/types';
|
import { log } from '../Types/types';
|
||||||
import { singleton } from 'tsyringe';
|
import { singleton } from 'tsyringe';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user