Files
psu-schedule/server/errors.js

59 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Errors the API reports to clients: an HTTP status, a stable machine-readable `code` and a
* message ready to show. Clients branch on the code, never on the wording of the message.
*
* 400 bad_request the request itself is wrong (missing or malformed parameters)
* 404 unknown_endpoint no such API address: the server is older than the client
* 404 document_not_found the document left the catalog
* 404 group_not_found the document has no such group
* 413 file_too_large an import over 10 MB
* 422 unreadable_file an import that is not a readable Word table
* 429 too_many_requests the client sends too much; Retry-After says when to come back
* 429 busy the server is parsing other imports
* 502 source_unavailable the university catalog did not answer
* 502 source_invalid the catalog answered, but its folders or tables are not recognised
* 504 source_timeout the university catalog answered too slowly
* 500 internal a fault of the server itself
*/
export class ApiError extends Error {
constructor(status, code, message) {
super(message);
this.status = status;
this.code = code;
}
}
export const apiError = (status, code, message) => new ApiError(status, code, message);
const SOURCE_DOWN = "Каталог университета сейчас не отвечает. Попробуйте позже.";
const SOURCE_SLOW = "Каталог университета отвечает слишком долго. Попробуйте позже.";
/**
* A failed download from the university as an API error: curl's exit code 28 (or our own
* kill on the time limit) is a timeout, any other failure means the source is unavailable.
*/
export function sourceError(error) {
if (error instanceof ApiError) return error;
const timedOut = error?.code === 28 || error?.killed || error?.signal === "SIGTERM";
return timedOut
? new ApiError(504, "source_timeout", SOURCE_SLOW)
: new ApiError(502, "source_unavailable", SOURCE_DOWN);
}
/** Status, code and message for any error that reached the error handler. */
export function describe(error) {
if (error instanceof ApiError)
return { status: error.status, code: error.code, message: error.message };
if (error?.code === "LIMIT_FILE_SIZE")
return {
status: 413,
code: "file_too_large",
message: "Файл больше 10 МБ. Выберите документ меньшего размера.",
};
return {
status: 500,
code: "internal",
message: "Не удалось загрузить расписание. Проверьте подключение и попробуйте ещё раз.",
};
}