|
| 1 | +import axios from 'axios'; |
| 2 | +import {apiURL} from '@/env'; |
| 3 | +import {getLocalHFToken, getLocalToken, removeLocalToken} from '@/utils'; |
| 4 | +import Vue from 'vue'; |
| 5 | +import {TYPE} from 'vue-toastification'; |
| 6 | +import ErrorToast from '@/views/main/utils/ErrorToast.vue'; |
| 7 | +import router from '@/router'; |
| 8 | +import mixpanel from 'mixpanel-browser'; |
| 9 | +import {useUserStore} from '@/stores/user'; |
| 10 | +import { |
| 11 | + AccountControllerApi, |
| 12 | + CatalogControllerApi, |
| 13 | + Configuration, |
| 14 | + DatasetsControllerApi, |
| 15 | + DevControllerApi, |
| 16 | + DownloadControllerApi, |
| 17 | + ErrorContext, |
| 18 | + FeedbackControllerApi, |
| 19 | + InspectionControllerApi, |
| 20 | + LicenseControllerApi, |
| 21 | + Middleware, |
| 22 | + MlWorkerControllerApi, |
| 23 | + MlWorkerJobControllerApi, |
| 24 | + ModelControllerApi, |
| 25 | + ProjectControllerApi, |
| 26 | + PublicUserControllerApi, |
| 27 | + ResponseContext, |
| 28 | + SettingsControllerApi, |
| 29 | + SetupControllerApi, |
| 30 | + SlicingFunctionControllerApi, |
| 31 | + TestControllerApi, |
| 32 | + TestFunctionControllerApi, |
| 33 | + TestSuiteControllerApi, |
| 34 | + TransformationFunctionControllerApi, |
| 35 | + UploadControllerApi, |
| 36 | + UserAdminControllerApi, |
| 37 | + UserJwtControllerApi |
| 38 | +} from "@/generated/client"; |
| 39 | + |
| 40 | + |
| 41 | +function hfRequestInterceptor(config) { |
| 42 | + // Do something before request is sent |
| 43 | + let hfToken = getLocalHFToken(); |
| 44 | + if (hfToken && config && config.headers) { |
| 45 | + config.headers.Authorization = `Bearer ${hfToken}`; |
| 46 | + } |
| 47 | + return config; |
| 48 | +} |
| 49 | + |
| 50 | +const huggingface = axios.create(); |
| 51 | +huggingface.interceptors.request.use(hfRequestInterceptor); |
| 52 | + |
| 53 | +function replacePlaceholders(detail: string) { |
| 54 | + return detail.replaceAll('GISKARD_ADDRESS', window.location.hostname); |
| 55 | +} |
| 56 | + |
| 57 | +async function trackError(ctx: ResponseContext, data: any) { |
| 58 | + let response = ctx.response; |
| 59 | + try { |
| 60 | + const trackingData = { |
| 61 | + method: ctx.init.method, |
| 62 | + code: response.status, |
| 63 | + message: response.statusText, |
| 64 | + ...data |
| 65 | + }; |
| 66 | + mixpanel.track('API error', trackingData); |
| 67 | + } catch (e) { |
| 68 | + console.error('Failed to track API Error', e); |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | + |
| 73 | +async function errorInterceptor(context: ResponseContext): Promise<Response | void> { |
| 74 | + const response = context.response; |
| 75 | + let data: any; |
| 76 | + try { |
| 77 | + data = await response.json(); |
| 78 | + } catch (e) { |
| 79 | + data = {}; |
| 80 | + } |
| 81 | + debugger |
| 82 | + await trackError(context, data); |
| 83 | + |
| 84 | + if (response.status === 401) { |
| 85 | + const userStore = useUserStore(); |
| 86 | + removeLocalToken(); |
| 87 | + userStore.token = ''; |
| 88 | + userStore.isLoggedIn = false; |
| 89 | + if (router.currentRoute.path !== '/auth/login') { |
| 90 | + await router.push('/auth/login'); |
| 91 | + } |
| 92 | + } else { |
| 93 | + let title: string; |
| 94 | + let detail: string; |
| 95 | + let stack: string | undefined = undefined; |
| 96 | + if (response.status === 502) { |
| 97 | + title = response.statusText; |
| 98 | + detail = "Error while connecting to Giskard server, check that it's running"; |
| 99 | + } else { |
| 100 | + title = data.title || response.statusText; |
| 101 | + detail = data.detail || response.url; |
| 102 | + stack = data.stack; |
| 103 | + } |
| 104 | + |
| 105 | + detail = replacePlaceholders(detail); |
| 106 | + |
| 107 | + Vue.$toast( |
| 108 | + { |
| 109 | + component: ErrorToast, |
| 110 | + props: { |
| 111 | + title: title || 'Error', |
| 112 | + detail: detail, |
| 113 | + stack: stack, |
| 114 | + }, |
| 115 | + }, |
| 116 | + { |
| 117 | + toastClassName: 'response-toast', |
| 118 | + type: TYPE.ERROR, |
| 119 | + } |
| 120 | + ); |
| 121 | + } |
| 122 | + |
| 123 | + return Promise.reject(response); |
| 124 | +} |
| 125 | + |
| 126 | + |
| 127 | +export class APIMiddleware implements Middleware { |
| 128 | + async post(context: ResponseContext): Promise<Response | void> { |
| 129 | + if (context.response.ok) { |
| 130 | + return Promise.resolve(context.response) |
| 131 | + } |
| 132 | + return await errorInterceptor(context); |
| 133 | + } |
| 134 | + |
| 135 | + onError(context: ErrorContext): Promise<Response | void> { |
| 136 | + Vue.$toast( |
| 137 | + { |
| 138 | + component: ErrorToast, |
| 139 | + props: { |
| 140 | + title: (context.error as any).message || 'Error', |
| 141 | + detail: context.url, |
| 142 | + }, |
| 143 | + }, |
| 144 | + { |
| 145 | + toastClassName: 'response-toast', |
| 146 | + type: TYPE.ERROR, |
| 147 | + } |
| 148 | + ); |
| 149 | + return Promise.resolve(context.response); |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | + |
| 154 | +const configuration = new Configuration({ |
| 155 | + basePath: apiURL, |
| 156 | + accessToken: (_name?: string) => getLocalToken() || '', |
| 157 | + middleware: [new APIMiddleware()], |
| 158 | +}); |
| 159 | +export const openapi = { |
| 160 | + settings: new SettingsControllerApi(configuration), |
| 161 | + projects: new ProjectControllerApi(configuration), |
| 162 | + account: new AccountControllerApi(configuration), |
| 163 | + catalog: new CatalogControllerApi(configuration), |
| 164 | + datasets: new DatasetsControllerApi(configuration), |
| 165 | + dev: new DevControllerApi(configuration), |
| 166 | + download: new DownloadControllerApi(configuration), |
| 167 | + feedback: new FeedbackControllerApi(configuration), |
| 168 | + inspection: new InspectionControllerApi(configuration), |
| 169 | + license: new LicenseControllerApi(configuration), |
| 170 | + mlWorker: new MlWorkerControllerApi(configuration), |
| 171 | + mlWorkerJob: new MlWorkerJobControllerApi(configuration), |
| 172 | + model: new ModelControllerApi(configuration), |
| 173 | + project: new ProjectControllerApi(configuration), |
| 174 | + publicUser: new PublicUserControllerApi(configuration), |
| 175 | + setup: new SetupControllerApi(configuration), |
| 176 | + slicingFunction: new SlicingFunctionControllerApi(configuration), |
| 177 | + test: new TestControllerApi(configuration), |
| 178 | + testFunction: new TestFunctionControllerApi(configuration), |
| 179 | + testSuite: new TestSuiteControllerApi(configuration), |
| 180 | + transformationFunction: new TransformationFunctionControllerApi(configuration), |
| 181 | + upload: new UploadControllerApi(configuration), |
| 182 | + userAdmin: new UserAdminControllerApi(configuration), |
| 183 | + userJwt: new UserJwtControllerApi(configuration), |
| 184 | +}; |
0 commit comments