masto
Version:
Mastodon API client for JavaScript, TypeScript, Node.js, browsers
82 lines (81 loc) • 3.2 kB
JavaScript
import { MastoHttpError, MastoTimeoutError, MastoUnexpectedError, } from "../errors/index.js";
import { BaseHttp } from "./base-http.js";
import { getEncoding } from "./get-encoding.js";
export class HttpNativeImpl extends BaseHttp {
serializer;
config;
logger;
constructor(serializer, config, logger) {
super();
this.serializer = serializer;
this.config = config;
this.logger = logger;
}
async request(params) {
const request = this.createRequest(params);
try {
this.logger?.log("info", `↑ ${request.method} ${request.url}`);
this.logger?.log("debug", "\tbody", {
encoding: params.encoding,
body: params.body,
});
const response = await fetch(request);
if (!response.ok) {
throw response;
}
const text = await response.text();
const encoding = getEncoding(response.headers);
if (!encoding) {
throw new MastoUnexpectedError("The server returned data with an unknown encoding.");
}
const data = this.serializer.deserialize(encoding, text);
this.logger?.log("info", `↓ ${request.method} ${request.url}`);
this.logger?.log("debug", "\tbody", text);
return {
headers: response.headers,
data: data,
};
}
catch (error) {
this.logger?.log("debug", `HTTP failed`, error);
throw await this.createError(error);
}
}
createRequest(params) {
const { method, path, search, encoding = "json", requestInit = {}, } = params;
const url = this.config.resolvePath(path, search);
const body = this.serializer.serialize(encoding, params.body);
const init = this.config.mergeRequestInitWithDefaults(requestInit);
const request = new Request(url, {
method,
body,
...init,
});
if (typeof body === "string" && encoding === "json") {
request.headers.set("Content-Type", "application/json");
}
return request;
}
async createError(error) {
if (error instanceof Response) {
const encoding = getEncoding(error.headers);
if (!encoding) {
throw new MastoUnexpectedError("The server returned data with an unknown encoding. The server may be down.");
}
const data = this.serializer.deserialize(encoding, await error.text());
const { error: message, errorDescription, details, ...additionalProperties } = data;
return new MastoHttpError({
statusCode: error.status,
message: message,
description: errorDescription,
details: details,
additionalProperties,
}, { cause: error });
}
if (error instanceof DOMException && error.name === "TimeoutError") {
return new MastoTimeoutError(`Request timed out`, { cause: error });
}
/* c8 ignore next */
return error;
}
}