Skip to content

Commit

Permalink
Merge pull request #1097 from JKRhb/http-strict-boolean
Browse files Browse the repository at this point in the history
chore(binding-http): enable eslint/strict-boolean-expressions
  • Loading branch information
relu91 authored Oct 13, 2023
2 parents 63b31c6 + 4624a03 commit b8aeef6
Show file tree
Hide file tree
Showing 18 changed files with 272 additions and 201 deletions.
5 changes: 4 additions & 1 deletion packages/binding-http/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": "../../.eslintrc.js"
"extends": "../../.eslintrc.js",
"rules": {
"@typescript-eslint/strict-boolean-expressions": ["error"]
}
}
23 changes: 18 additions & 5 deletions packages/binding-http/src/codecs/tuya-codec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,30 @@ import { ContentCodec } from "@node-wot/core";
import * as TD from "@node-wot/td-tools";
import { DataSchemaValue } from "wot-typescript-definitions";

interface TuyaOutput {
success?: boolean;
msg?: string;
result?: {
code?: string;
}[];
}

export default class HttpTuyaCodec implements ContentCodec {
getMediaType(): string {
return "application/json+tuya";
}

bytesToValue(bytes: Buffer, schema: TD.DataSchema, parameters: { [key: string]: string }): DataSchemaValue {
const parsedBody = JSON.parse(bytes.toString());
if (!parsedBody.success) throw new Error(parsedBody.msg ? parsedBody.msg : JSON.stringify(parsedBody));
for (const key in parsedBody.result) {
if (parsedBody.result[key].code === schema["tuya:PropertyName"]) {
return parsedBody.result[key].value;
const parsedBody: TuyaOutput = JSON.parse(bytes.toString());
const success = parsedBody.success ?? false;

if (!success) {
throw new Error(parsedBody.msg != null ? parsedBody.msg : JSON.stringify(parsedBody));
}

for (const value of Object.values(parsedBody.result ?? {})) {
if (value.code === schema["tuya:PropertyName"]) {
return value;
}
}
throw new Error("Property not found");
Expand Down
58 changes: 43 additions & 15 deletions packages/binding-http/src/credential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,18 @@ export interface TuyaCustomBearerCredentialConfiguration {
secret: string;
}

interface TokenResponse {
success?: boolean;
result?: {
// eslint-disable-next-line camelcase
access_token?: string;
// eslint-disable-next-line camelcase
refresh_token?: string;
// eslint-disable-next-line camelcase
expire_time?: number;
};
}

export class TuyaCustomBearer extends Credential {
protected key: string;
protected secret: string;
Expand All @@ -184,14 +196,15 @@ export class TuyaCustomBearer extends Credential {
await this.requestAndRefreshToken(isTokenExpired);

const url: string = request.url;
const body = request.body ? request.body.read().toString() : "";
const headers = this.getHeaders(true, request.headers.raw(), body, url, request.method);
const body = request.body?.read().toString();
const method = request.method;
const headers = this.getHeaders(true, request.headers.raw(), body, url, method);
Object.assign(headers, request.headers.raw());
return new Request(url, { method: request.method, body: body !== "" ? body : undefined, headers });
return new Request(url, { method, body: body !== "" ? body : undefined, headers });
}

protected async requestAndRefreshToken(refresh: boolean): Promise<void> {
const headers = this.getHeaders(false, {}, "");
const headers = this.getHeaders(false, {});
const request = {
headers,
method: "GET",
Expand All @@ -200,36 +213,51 @@ export class TuyaCustomBearer extends Credential {
if (refresh) {
url = `${this.baseUri}/token/${this.refreshToken}`;
}
const data = await (await fetch(url, request)).json();
if (data.success) {
this.token = data.result.access_token;
this.refreshToken = data.result.refresh_token;
this.expireTime = new Date(Date.now() + data.result.expire_time * 1000);
const data: TokenResponse = await (await fetch(url, request)).json();
const success = data.success ?? false;

if (success) {
this.token = data.result?.access_token;
this.refreshToken = data.result?.refresh_token;

const expireTime = data.result?.expire_time;
if (expireTime != null) {
this.expireTime = new Date(Date.now() + expireTime * 1000);
}
} else {
throw new Error("token fetch failed");
}
}

private getHeaders(NormalRequest: boolean, headers: unknown, body: string, url?: string, method?: string) {
private getHeaders(NormalRequest: boolean, headers: unknown, body?: string, url?: string, method?: string) {
const requestTime = Date.now().toString();
const replaceUri = this.baseUri.replace("/v1.0", "");
const _url = url ? url.replace(`${replaceUri}`, "") : undefined;
const _url = url?.replace(replaceUri, "");
const sign = this.requestSign(NormalRequest, requestTime, body, _url, method);
return {
t: requestTime,
client_id: this.key,
sign_method: "HMAC-SHA256",
sign,
access_token: this.token || "",
access_token: this.token ?? "",
};
}

private requestSign(NormalRequest: boolean, requestTime: string, body: string, path = "", method?: string): string {
const bodyHash = crypto.createHash("sha256").update(body).digest("hex");
private requestSign(
NormalRequest: boolean,
requestTime: string,
body?: string,
path = "",
method?: string
): string {
const bodyHash = crypto
.createHash("sha256")
.update(body ?? "")
.digest("hex");
let signUrl = "/v1.0/token?grant_type=1";
const headerString = "";
let useToken = "";
const _method = method || "GET";
const _method = method ?? "GET";
if (NormalRequest) {
useToken = this.token ?? "";
const pathQuery = queryString.parse(path.split("?")[1]);
Expand Down
10 changes: 5 additions & 5 deletions packages/binding-http/src/http-client-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export default class HttpClient implements ProtocolClient {
}

public async invokeResource(form: HttpForm, content?: Content): Promise<Content> {
const headers = content ? [["content-type", content.type]] : [];
const headers = content != null ? [["content-type", content.type]] : [];

const request = await this.generateFetchRequest(form, "POST", {
headers,
Expand All @@ -184,8 +184,8 @@ export default class HttpClient implements ProtocolClient {

debug(
`HttpClient (invokeResource) sending ${request.method} ${
content ? "with '" + request.headers.get("Content-Type") + "' " : " "
}to ${request.url}`
content != null ? `with '"${request.headers.get("Content-Type")}"` : ""
} to ${request.url}`
);

const result = await this.fetch(request);
Expand Down Expand Up @@ -218,7 +218,7 @@ export default class HttpClient implements ProtocolClient {

public async stop(): Promise<void> {
// When running in browser mode, Agent.destroy() might not exist.
if (this.agent && this.agent.destroy) this.agent.destroy();
this.agent?.destroy?.();
}

public setSecurity(metadata: Array<TD.SecurityScheme>, credentials?: unknown): boolean {
Expand Down Expand Up @@ -280,7 +280,7 @@ export default class HttpClient implements ProtocolClient {
return false;
}

if (security.proxy) {
if (security.proxy != null) {
if (this.proxyRequest !== null) {
debug(`HttpClient overriding client-side proxy with security proxy '${security.proxy}`);
}
Expand Down
Loading

0 comments on commit b8aeef6

Please sign in to comment.