fake-iamport-server
Version:
Fake iamport server for testing
82 lines (76 loc) • 3.15 kB
text/typescript
import { SharedLock, SharedMutex, UniqueLock } from "tstl";
import { IConnection } from "./IConnection";
import { users } from "./functional";
import { IIamportResponse } from "./structures/IIamportResponse";
import { IIamportUser } from "./structures/IIamportUser";
/**
* 아임포트 커넥터.
*
* 아임포트가 발급해주는 유저 인증 토큰에는, 유효 시간 {@link IIamportUser.expired_at} 이
* 존재하여, 해당 시간을 초과하거든 기 발급 토큰이 만료되어 더 이상 쓸 수 없게 된다. 때문에
* 아임포트 API 를 호출할 때마다, 늘 토큰의 만료 시간을 신경 써줘야해서 매우 번거롭다.
*
* `IamportConnector` 는 이러한 번거로움을 없애기 위하여, 아임포트의 API 를 호출하기 위하여
* {@link IConnection} 정보하기 위한 {@link IamportConnector.connect} 메서드를 호출할 때마다,
* 아임포트 유저 인증 토큰의 만료 시간의 도래 여부를 계산하여 자동으로 갱신해주는 클래스이다.
*
* 따라서 아임포트 유저 토큰 고유의 시간 제한에 구애받지 않고, 아임포트의 API 들을 편하게 호출하고
* 싶다면, 현재 `IamportConnector` 의 적극적인 사용을 권하는 바이다.
*
* @author Samchon
*/
export class IamportConnector {
private readonly mutex_: SharedMutex;
private token_: IIamportUser | null;
/**
* Initializer Constructor
*
* @param host 아임포트 서버의 host 주소
* @param accessor 아임포트에서 발급해 준 API 및 secret 키
* @param surplus 만료 일시로부터의 여분 시간, 기본값은 15,000 ms
*/
public constructor(
public readonly host: string,
public readonly accessor: IIamportUser.IAccessor,
public readonly surplus: number = 15_000,
) {
this.mutex_ = new SharedMutex();
this.token_ = null;
}
/**
* 커넥션 정보 구성하기.
*
* 아임포트 API 를 호출하기 위한 {@link IConnection} 정보를 구성하여 리턴한다. 이 커넥션
* 정보에는 아임포트의 유저 인증 토큰이 함께하는데, 만일 해당 유저 인증 토큰의 만료 일시가
* 도래했다면, 이를 새로운 것으로 자동 갱신해준다.
*
* @returns 커넥션 정보 with 인증 토큰
*/
public async get(): Promise<IConnection> {
return {
host: this.host,
headers: {
Authorization: await this.getToken(),
},
};
}
private async getToken(): Promise<string> {
if (
this.token_ === null ||
Date.now() >= this.token_.expired_at * 1000 - this.surplus
) {
const locked: boolean = await UniqueLock.try_lock(
this.mutex_,
async () => {
const output: IIamportResponse<IIamportUser> = await users.getToken(
{ host: this.host },
this.accessor,
);
this.token_ = output.response;
},
);
if (locked === false) await SharedLock.lock(this.mutex_, () => {});
}
return this.token_!.access_token;
}
}