adding unreadable http response case and removing deprecated fields

This commit is contained in:
Sebastian 2023-04-07 18:46:25 -03:00
parent 958747bd08
commit cfe7129c4e
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
26 changed files with 437 additions and 206 deletions

View File

@ -172,6 +172,14 @@ export function handleNotOkResult(
});
break;
}
case ErrorType.UNREADABLE: {
notifyError({
title: i18n.str`Unexpected error.`,
description: `Response from ${result.info?.url} is unreadable, http status: ${result.status}`,
debug: JSON.stringify(result),
});
break;
}
case ErrorType.UNEXPECTED: {
notifyError({
title: i18n.str`Unexpected error.`,

View File

@ -160,6 +160,14 @@ export function LoginForm({ onRegister }: { onRegister?: () => void }): VNode {
});
break;
}
case ErrorType.UNREADABLE: {
saveError({
title: i18n.str`Unexpected error.`,
description: `Response from ${cause.info?.url} is unreadable, http status: ${cause.status}`,
debug: JSON.stringify(cause),
});
break;
}
default: {
saveError({
title: i18n.str`Unexpected error, please report.`,

View File

@ -151,6 +151,14 @@ export function buildRequestErrorMessage(
};
break;
}
case ErrorType.UNREADABLE: {
result = {
title: i18n.str`Unexpected error`,
description: `Response from ${cause.info?.url} is unreadable, status: ${cause.status}`,
debug: JSON.stringify(cause),
};
break;
}
case ErrorType.UNEXPECTED: {
result = {
title: i18n.str`Unexpected error`,

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
TranslationProvider,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -40,6 +41,7 @@ import { ConfigContextProvider } from "./context/config.js";
import { useBackendConfig } from "./hooks/backend.js";
import { strings } from "./i18n/strings.js";
import LoginPage from "./paths/login/index.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export function Application(): VNode {
return (
@ -77,47 +79,63 @@ function ApplicationStatusRoutes(): VNode {
);
}
if (result.clientError && result.isUnauthorized)
return (
<Fragment>
<NotYetReadyAppMenu title="Login" />
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
</Fragment>
);
if (result.clientError && result.isNotfound)
return (
if (!result.ok) {
if (result.loading) return <Loading />;
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
) {
return (
<Fragment>
<NotYetReadyAppMenu title="Login" />
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
</Fragment>
);
}
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
) {
return (
<Fragment>
<NotYetReadyAppMenu title="Error" />
<NotificationCard
notification={{
message: i18n.str`Server not found`,
type: "ERROR",
description: `Check your url`,
}}
/>
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
</Fragment>
);
}
if (result.type === ErrorType.SERVER) {
<Fragment>
<NotYetReadyAppMenu title="Error" />
<NotificationCard
notification={{
message: i18n.str`Server not found`,
type: "ERROR",
description: `Check your url`,
}}
/>
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
</Fragment>
);
if (result.serverError)
return (
<Fragment>
<NotYetReadyAppMenu title="Error" />
<NotificationCard
notification={{
message: i18n.str`Couldn't access the server`,
message: i18n.str`Server response with an error code`,
type: "ERROR",
description: i18n.str`Got message ${result.message} from ${result.info?.url}`,
}}
/>
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
</Fragment>
);
if (result.loading) return <Loading />;
if (!result.ok)
</Fragment>;
}
if (result.type === ErrorType.UNREADABLE) {
<Fragment>
<NotYetReadyAppMenu title="Error" />
<NotificationCard
notification={{
message: i18n.str`Response from server is unreadable, http status: ${result.status}`,
type: "ERROR",
description: i18n.str`Got message ${result.message} from ${result.info?.url}`,
}}
/>
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
</Fragment>;
}
return (
<Fragment>
<NotYetReadyAppMenu title="Error" />
@ -131,6 +149,7 @@ function ApplicationStatusRoutes(): VNode {
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
</Fragment>
);
}
return (
<div class="has-navbar-fixed-top">

View File

@ -18,7 +18,10 @@
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import {
ErrorType,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
import { createHashHistory } from "history";
import { Fragment, h, VNode } from "preact";
import { Router, Route, route } from "preact-router";
@ -32,6 +35,7 @@ import { useBackendInstancesTestForAdmin } from "./hooks/backend.js";
import { InstanceRoutes } from "./InstanceRoutes.js";
import LoginPage from "./paths/login/index.js";
import { INSTANCE_ID_LOOKUP } from "./utils/constants.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export function ApplicationReadyRoutes(): VNode {
const { i18n } = useTranslationContext();
@ -48,28 +52,30 @@ export function ApplicationReadyRoutes(): VNode {
route("/");
};
if (result.clientError && result.isUnauthorized) {
return (
<Fragment>
<NotYetReadyAppMenu title="Login" onLogout={clearTokenAndGoToRoot} />
<NotificationCard
notification={{
message: i18n.str`Access denied`,
description: i18n.str`Check your token is valid`,
type: "ERROR",
}}
/>
<LoginPage onConfirm={updateLoginStatus} />
</Fragment>
);
}
if (result.loading) return <NotYetReadyAppMenu title="Loading..." />;
let admin = true;
let instanceNameByBackendURL;
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
) {
return (
<Fragment>
<NotYetReadyAppMenu title="Login" onLogout={clearTokenAndGoToRoot} />
<NotificationCard
notification={{
message: i18n.str`Access denied`,
description: i18n.str`Check your token is valid`,
type: "ERROR",
}}
/>
<LoginPage onConfirm={updateLoginStatus} />
</Fragment>
);
}
const path = new URL(backendURL).pathname;
const match = INSTANCE_ID_LOOKUP.exec(path);
if (!match || !match[1]) {

View File

@ -178,8 +178,8 @@ export function InstanceRoutes({
message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
description: i18n.str`Diagnostic from ${error.info?.url} is '${error.message}'`,
details:
error.clientError || error.serverError
? error.error?.detail
error.type === ErrorType.CLIENT || error.type === ErrorType.SERVER
? error.payload.detail
: undefined,
type: "ERROR",
to,
@ -608,8 +608,9 @@ function AdminInstanceUpdatePage({
message: i18n.str`The backend reported a problem: HTTP status #${error.status}`,
description: i18n.str`Diagnostic from ${error.info?.url} is '${error.message}'`,
details:
error.clientError || error.serverError
? error.error?.detail
error.type === ErrorType.CLIENT ||
error.type === ErrorType.SERVER
? error.payload.detail
: undefined,
type: "ERROR" as const,
};

View File

@ -83,6 +83,7 @@ export class ApiMockEnvironment extends MockEnvironment {
status: !mocked ? 200 : mocked.status,
url: _url.href,
payload: options.data,
options: {},
},
};
}

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -32,6 +33,7 @@ import { MerchantBackend } from "../../../declaration.js";
import { useAdminAPI, useBackendInstances } from "../../../hooks/instance.js";
import { Notification } from "../../../utils/types.js";
import { View } from "./View.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onCreate: () => void;
@ -60,10 +62,20 @@ export default function Instances({
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { ErrorType, HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Loading } from "../../../components/exception/loading.js";
@ -22,6 +22,7 @@ import { useInstanceContext } from "../../../context/instance.js";
import { MerchantBackend } from "../../../declaration.js";
import { useInstanceAPI, useInstanceDetails } from "../../../hooks/instance.js";
import { DetailPage } from "./DetailPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -44,10 +45,20 @@ export default function Detail({
const { deleteInstance } = useInstanceAPI();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -19,12 +19,13 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { ErrorType, HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { Loading } from "../../../../components/exception/loading.js";
import { MerchantBackend } from "../../../../declaration.js";
import { useInstanceKYCDetails } from "../../../../hooks/instance.js";
import { ListPage } from "./ListPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -38,10 +39,20 @@ export default function ListKYC({
onNotFound,
}: Props): VNode {
const result = useInstanceKYCDetails();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
const status = result.data.type === "ok" ? undefined : result.data.status;

View File

@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { ErrorType, HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Loading } from "../../../../components/exception/loading.js";
@ -30,6 +30,7 @@ import { useOrderAPI } from "../../../../hooks/order.js";
import { useInstanceProducts } from "../../../../hooks/product.js";
import { Notification } from "../../../../utils/types.js";
import { CreatePage } from "./CreatePage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export type Entity = {
request: MerchantBackend.Orders.PostOrderRequest;
@ -55,19 +56,36 @@ export default function OrderCreate({
const detailsResult = useInstanceDetails();
const inventoryResult = useInstanceProducts();
if (detailsResult.clientError && detailsResult.isUnauthorized)
return onUnauthorized();
if (detailsResult.clientError && detailsResult.isNotfound)
return onNotFound();
if (detailsResult.loading) return <Loading />;
if (!detailsResult.ok) return onLoadError(detailsResult);
if (inventoryResult.clientError && inventoryResult.isUnauthorized)
return onUnauthorized();
if (inventoryResult.clientError && inventoryResult.isNotfound)
return onNotFound();
if (inventoryResult.loading) return <Loading />;
if (!inventoryResult.ok) return onLoadError(inventoryResult);
if (!detailsResult.ok) {
if (
detailsResult.type === ErrorType.CLIENT &&
detailsResult.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
detailsResult.type === ErrorType.CLIENT &&
detailsResult.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(detailsResult);
}
if (!inventoryResult.ok) {
if (
inventoryResult.type === ErrorType.CLIENT &&
inventoryResult.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
inventoryResult.type === ErrorType.CLIENT &&
inventoryResult.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(inventoryResult);
}
return (
<Fragment>

View File

@ -16,6 +16,7 @@
import {
useTranslationContext,
HttpError,
ErrorType,
} from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
@ -25,6 +26,7 @@ import { MerchantBackend } from "../../../../declaration.js";
import { useOrderAPI, useOrderDetails } from "../../../../hooks/order.js";
import { Notification } from "../../../../utils/types.js";
import { DetailPage } from "./DetailPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export interface Props {
oid: string;
@ -48,10 +50,20 @@ export default function Update({
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -37,6 +38,7 @@ import {
import { Notification } from "../../../../utils/types.js";
import { ListPage } from "./ListPage.js";
import { RefundModal } from "./Table.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -71,10 +73,20 @@ export default function OrderList({
undefined,
);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
const isPaidActive = filter.paid === "yes" ? "is-active" : "";
const isRefundedActive = filter.refunded === "yes" ? "is-active" : "";
@ -195,10 +207,20 @@ function RefundModalForTable({
}: RefundProps): VNode {
const result = useOrderDetails(id);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<RefundModal

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -34,6 +35,7 @@ import {
} from "../../../../hooks/product.js";
import { Notification } from "../../../../utils/types.js";
import { CardTable } from "./Table.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -55,10 +57,20 @@ export default function ProductList({
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<section class="section is-main-section">

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -31,6 +32,7 @@ import { MerchantBackend } from "../../../../declaration.js";
import { useProductAPI, useProductDetails } from "../../../../hooks/product.js";
import { Notification } from "../../../../utils/types.js";
import { UpdatePage } from "./UpdatePage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export type Entity = MerchantBackend.Products.ProductAddDetail;
interface Props {
@ -55,10 +57,20 @@ export default function UpdateProduct({
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -19,12 +19,13 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { ErrorType, HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact";
import { Loading } from "../../../../components/exception/loading.js";
import { MerchantBackend } from "../../../../declaration.js";
import { useReserveDetails } from "../../../../hooks/reserves.js";
import { DetailPage } from "./DetailPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
rid: string;
@ -45,10 +46,20 @@ export default function DetailReserve({
}: Props): VNode {
const result = useReserveDetails(rid);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>
<DetailPage selected={result.data} onBack={onBack} id={rid} />

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -35,6 +36,7 @@ import {
import { Notification } from "../../../../utils/types.js";
import { AuthorizeTipModal } from "./AutorizeTipModal.js";
import { CardTable } from "./Table.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -67,10 +69,20 @@ export default function ListTips({
TipConfirmation | undefined
>(undefined);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<section class="section is-main-section">

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -34,6 +35,7 @@ import {
} from "../../../../hooks/templates.js";
import { Notification } from "../../../../utils/types.js";
import { ListPage } from "./ListPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -60,10 +62,20 @@ export default function ListTemplates({
const { deleteTemplate } = useTemplateAPI();
const result = useInstanceTemplates({ position }, (id) => setPosition(id));
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -34,6 +35,7 @@ import {
} from "../../../../hooks/templates.js";
import { Notification } from "../../../../utils/types.js";
import { QrPage } from "./QrPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export type Entity = MerchantBackend.Transfers.TransferInformation;
interface Props {
@ -54,10 +56,20 @@ export default function TemplateQrPage({
const result = useTemplateDetails(tid);
const [notif, setNotif] = useState<Notification | undefined>(undefined);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<>

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -34,6 +35,7 @@ import {
} from "../../../../hooks/templates.js";
import { Notification } from "../../../../utils/types.js";
import { UpdatePage } from "./UpdatePage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId;
@ -59,10 +61,20 @@ export default function UpdateTemplate({
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -34,6 +35,7 @@ import {
} from "../../../../hooks/templates.js";
import { Notification } from "../../../../utils/types.js";
import { UsePage } from "./UsePage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export type Entity = MerchantBackend.Transfers.TransferInformation;
interface Props {
@ -58,10 +60,20 @@ export default function TemplateUsePage({
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<>

View File

@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
import { HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { ErrorType, HttpError } from "@gnu-taler/web-util/lib/index.browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Loading } from "../../../../components/exception/loading.js";
@ -27,6 +27,7 @@ import { MerchantBackend } from "../../../../declaration.js";
import { useInstanceDetails } from "../../../../hooks/instance.js";
import { useInstanceTransfers } from "../../../../hooks/transfer.js";
import { ListPage } from "./ListPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -68,10 +69,20 @@ export default function ListTransfer({
(id) => setPosition(id),
);
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<ListPage

View File

@ -14,6 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import {
ErrorType,
HttpError,
HttpResponse,
useTranslationContext,
@ -32,6 +33,7 @@ import {
} from "../../../hooks/instance.js";
import { Notification } from "../../../utils/types.js";
import { UpdatePage } from "./UpdatePage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export interface Props {
onBack: () => void;
@ -78,10 +80,20 @@ function CommonUpdate(
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -34,6 +35,7 @@ import {
} from "../../../../hooks/webhooks.js";
import { Notification } from "../../../../utils/types.js";
import { ListPage } from "./ListPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
interface Props {
onUnauthorized: () => VNode;
@ -56,10 +58,20 @@ export default function ListWebhooks({
const { deleteWebhook } = useWebhookAPI();
const result = useInstanceWebhooks({ position }, (id) => setPosition(id));
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -20,6 +20,7 @@
*/
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/lib/index.browser";
@ -34,6 +35,7 @@ import {
} from "../../../../hooks/webhooks.js";
import { Notification } from "../../../../utils/types.js";
import { UpdatePage } from "./UpdatePage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
export type Entity = MerchantBackend.Webhooks.WebhookPatchDetails & WithId;
@ -59,10 +61,20 @@ export default function UpdateWebhook({
const { i18n } = useTranslationContext();
if (result.clientError && result.isUnauthorized) return onUnauthorized();
if (result.clientError && result.isNotfound) return onNotFound();
if (result.loading) return <Loading />;
if (!result.ok) return onLoadError(result);
if (!result.ok) {
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.Unauthorized
)
return onUnauthorized();
if (
result.type === ErrorType.CLIENT &&
result.status === HttpStatusCode.NotFound
)
return onNotFound();
return onLoadError(result);
}
return (
<Fragment>

View File

@ -20,6 +20,7 @@ import { base64encode } from "./base64.js";
export enum ErrorType {
CLIENT,
SERVER,
UNREADABLE,
TIMEOUT,
UNEXPECTED,
}
@ -97,12 +98,9 @@ export async function defaultRequestHandler<T>(
url: _url.href,
hasToken: !!options.token,
status: 0,
options,
};
const error: HttpRequestTimeoutError = {
clientError: true,
isNotfound: false,
isUnauthorized: false,
error: undefined,
info,
type: ErrorType.TIMEOUT,
message: "Request timeout",
@ -124,6 +122,7 @@ export async function defaultRequestHandler<T>(
_url.href,
payload,
!!options.token,
options,
);
return result;
} else {
@ -132,6 +131,7 @@ export async function defaultRequestHandler<T>(
_url.href,
payload,
!!options.token,
options,
);
throw new RequestError(error);
}
@ -152,6 +152,7 @@ export interface RequestInfo {
hasToken: boolean;
payload: any;
status: number;
options: RequestOptions;
}
interface HttpResponseLoading<T> {
@ -185,103 +186,60 @@ export type HttpError<ErrorDetail> =
| HttpRequestTimeoutError
| HttpResponseClientError<ErrorDetail>
| HttpResponseServerError<ErrorDetail>
| HttpResponseUnreadableError
| HttpResponseUnexpectedError;
export interface HttpResponseServerError<ErrorDetail> {
ok?: false;
loading?: false;
/**
* @deprecated use status
*/
clientError?: false;
/**
* @deprecated use status
*/
serverError: true;
type: ErrorType.SERVER;
/**
* @deprecated use payload
*/
error: ErrorDetail;
payload: ErrorDetail;
status: HttpStatusCode;
message: string;
info?: RequestInfo;
info: RequestInfo;
}
interface HttpRequestTimeoutError {
ok?: false;
loading?: false;
/**
* @deprecated use type
*/
clientError: true;
/**
* @deprecated use type
*/
serverError?: false;
type: ErrorType.TIMEOUT;
info?: RequestInfo;
error: undefined;
info: RequestInfo;
isUnauthorized: false;
isNotfound: false;
message: string;
}
interface HttpResponseClientError<ErrorDetail> {
ok?: false;
loading?: false;
/**
* @deprecated use type
*/
clientError: true;
/**
* @deprecated use type
*/
serverError?: false;
type: ErrorType.CLIENT;
info?: RequestInfo;
/**
* @deprecated use status
*/
isUnauthorized: boolean;
/**
* @deprecated use status
*/
isNotfound: boolean;
info: RequestInfo;
status: HttpStatusCode;
/**
* @deprecated use payload
*/
error: ErrorDetail;
payload: ErrorDetail;
message: string;
}
interface HttpResponseUnexpectedError {
ok?: false;
loading?: false;
/**
* @deprecated use type
*/
clientError?: false;
/**
* @deprecated use type
*/
serverError?: false;
loading: false;
type: ErrorType.UNEXPECTED;
info?: RequestInfo;
info: RequestInfo;
status?: HttpStatusCode;
/**
* @deprecated use exception
*/
error: unknown;
exception: unknown;
message: string;
}
interface HttpResponseUnreadableError {
ok?: false;
loading: false;
type: ErrorType.UNREADABLE;
info: RequestInfo;
status: HttpStatusCode;
exception: unknown;
body: string;
message: string;
}
export class RequestError<ErrorDetail> extends Error {
/**
* @deprecated use cause
@ -317,6 +275,7 @@ async function buildRequestOk<T>(
url: string,
payload: any,
hasToken: boolean,
options: RequestOptions,
): Promise<HttpResponseOk<T>> {
const dataTxt = await response.text();
const data = dataTxt ? JSON.parse(dataTxt) : undefined;
@ -327,6 +286,7 @@ async function buildRequestOk<T>(
payload,
url,
hasToken,
options,
status: response.status,
},
};
@ -337,9 +297,11 @@ async function buildRequestFailed<ErrorDetail>(
url: string,
payload: any,
hasToken: boolean,
options: RequestOptions,
): Promise<
| HttpResponseClientError<ErrorDetail>
| HttpResponseServerError<ErrorDetail>
| HttpResponseUnreadableError
| HttpResponseUnexpectedError
> {
const status = response?.status;
@ -348,62 +310,52 @@ async function buildRequestFailed<ErrorDetail>(
payload,
url,
hasToken,
options,
status: status || 0,
};
const dataTxt = await response.text();
try {
const dataTxt = await response.text();
const data = dataTxt ? JSON.parse(dataTxt) : undefined;
if (status && status >= 400 && status < 500) {
const error: HttpResponseClientError<ErrorDetail> = {
clientError: true,
isNotfound: status === 404,
isUnauthorized: status === 401,
type: ErrorType.CLIENT,
status,
info,
message: data?.hint,
error: data, // remove this
payload: data,
};
return error;
}
if (status && status >= 500 && status < 600) {
const error: HttpResponseServerError<ErrorDetail> = {
serverError: true,
type: ErrorType.SERVER,
status,
info,
message: `${data?.hint} (code ${data?.code})`,
error: data, //remove this
payload: data,
};
return error;
}
return {
info,
loading: false,
type: ErrorType.UNEXPECTED,
status,
error: {}, // remove this
exception: undefined,
message: "NOT DEFINED",
message: `http status code not handled: ${status}`,
};
} catch (ex) {
const error: HttpResponseUnexpectedError = {
const error: HttpResponseUnreadableError = {
info,
loading: false,
status,
type: ErrorType.UNEXPECTED,
error: ex,
type: ErrorType.UNREADABLE,
exception: ex,
message: "NOT DEFINED",
body: dataTxt,
message: "Could not parse body as json",
};
return error;
}
}
// export function isAxiosError<T>(
// error: AxiosError | any,
// ): error is AxiosError<T> {
// return error && error.isAxiosError;
// }