Files
openstapps/frontend/app/src/app/modules/auth/capacitor-requestor.ts
T
2026-10-12 15:54:21 +02:00

109 lines
2.9 KiB
TypeScript

/*
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
AppAuthError,
Requestor,
} from '@openid/appauth';
import {
CapacitorHttp,
HttpHeaders,
HttpOptions,
} from '@capacitor/core';
type XhrSettings = Parameters<Requestor['xhr']>[0];
export class CapacitorRequestor implements Requestor {
public async xhr<T>(settings: XhrSettings): Promise<T> {
if (!settings.url) {
throw new AppAuthError('A URL must be provided.');
}
const method = (settings.method ?? 'GET').toUpperCase();
const url = new URL(settings.url);
let data: unknown;
if (settings.data) {
if (method === 'POST') {
data = settings.data;
} else {
const searchParams = new URLSearchParams(settings.data);
searchParams.forEach((value, key) => {
url.searchParams.append(key, value);
});
}
}
const options: HttpOptions = {
url: url.toString(),
method,
headers: this.getHeaders(settings.headers),
data,
};
if (settings.dataType?.toLowerCase() === 'json') {
options.responseType = 'json';
}
const response = await CapacitorHttp.request(options);
if (response.status < 200 || response.status >= 300) {
const body = this.parseBody(response.data);
/*
* Use the OAuth error code (e.g. 'invalid_grant') as message when the
* server sent one (RFC 6749, 5.2), so callers can tell a rejected
* refresh token apart from temporary failures.
*/
throw new AppAuthError(
typeof body?.error === 'string' ? body.error : `HTTP ${response.status}`,
body ?? response.data,
);
}
return response.data as T;
}
private parseBody(data: unknown): Record<string, unknown> | undefined {
if (typeof data === 'string') {
try {
data = JSON.parse(data);
} catch {
return undefined;
}
}
return data !== null && typeof data === 'object' ? (data as Record<string, unknown>) : undefined;
}
private getHeaders(headers: XhrSettings['headers']): HttpHeaders {
const result: HttpHeaders = {};
if (!headers) {
return result;
}
for (const [key, value] of Object.entries(headers)) {
if (value !== undefined && value !== null) {
result[key] = String(value);
}
}
return result;
}
}