Skip to content

Commit

Permalink
Replace Axios with Fetch (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
JorWo authored Mar 2, 2024
1 parent 69b4fc4 commit 2f24c9c
Show file tree
Hide file tree
Showing 14 changed files with 1,289 additions and 1,210 deletions.
3 changes: 1 addition & 2 deletions ui/api-handshake.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const axios = require('axios');
const env = require('@next/env');

env.loadEnvConfig(process.cwd());
Expand All @@ -23,7 +22,7 @@ or check the connection configuration and
fix any possible problems.\n`;

if (apiHandshakeEnabled) {
axios.get(`${apiBaseUrl}/`)
fetch(`${apiBaseUrl}/`)
.catch(() => {
console.log(errorMessage);
process.exit(1);
Expand Down
2 changes: 1 addition & 1 deletion ui/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const config: Config = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleDirectories: ['node_modules', '<rootDir>'],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1"
'^@/(.*)$': '<rootDir>/src/$1'
}
};

Expand Down
3 changes: 0 additions & 3 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-slot": "^1.0.2",
"axios": "^1.6.7",
"axios-retry": "^4.0.0",
"camaro": "^6.2.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
Expand All @@ -43,7 +41,6 @@
"@typescript-eslint/eslint-plugin": "^6.19.1",
"@typescript-eslint/parser": "^6.19.1",
"autoprefixer": "^10.0.1",
"axios-mock-adapter": "^1.22.0",
"eslint": "^8",
"eslint-config-next": "14.1.0",
"eslint-plugin-testing-library": "^6.2.0",
Expand Down
31 changes: 8 additions & 23 deletions ui/src/access/AuthorizationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import User from './User';
import Role from './Role';
import axios from 'axios';

const apiBaseUrl = process.env.NEXT_PUBLIC_API_2_1_BASE_URL as string;

Expand Down Expand Up @@ -33,17 +32,10 @@ export const setRoles = async (user: User): Promise<void> => {
*
* @returns True if the uhIdentifier is an owner of a grouping
*/
const isOwner = async (uhIdentifier: string): Promise<boolean> => {
try {
const { data } = await axios.get(`${apiBaseUrl}/owners`, {
headers: { 'current_user': uhIdentifier }
});
return data;
} catch (error) {
console.error(error);
}
return false;
}
const isOwner = async (uhIdentifier: string): Promise<boolean> =>
await fetch(`${apiBaseUrl}/owners`, { headers: { 'current_user': uhIdentifier }})
.then(res => res.json())
.catch(() => false);

/**
* Calls UH Groupings API to check if the uhIdentifier is an admin.
Expand All @@ -52,17 +44,10 @@ const isOwner = async (uhIdentifier: string): Promise<boolean> => {
*
* @returns True if the uhIdentifier is an admin
*/
const isAdmin = async (uhIdentifier: string): Promise<boolean> => {
try {
const { data } = await axios.get(`${apiBaseUrl}/admins`, {
headers: { 'current_user': uhIdentifier }
});
return data;
} catch (error) {
console.error(error);
}
return false;
}
const isAdmin = async (uhIdentifier: string): Promise<boolean> =>
await fetch(`${apiBaseUrl}/admins`, { headers: { 'current_user': uhIdentifier }})
.then(res => res.json())
.catch(() => false);

/**
* Checks if uhUuid is valid using Regex.
Expand Down
10 changes: 6 additions & 4 deletions ui/src/access/Saml11Validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import User, { AnonymousUser } from './User';
import uniqid from 'uniqid';
import { format } from 'util';
import { transform } from 'camaro';
import axios from 'axios';

const baseUrl = process.env.NEXT_PUBLIC_BASE_URL as string;
const casUrl = process.env.NEXT_PUBLIC_CAS_URL as string;
Expand Down Expand Up @@ -30,10 +29,13 @@ export const validateTicket = async (ticket: string): Promise<User> => {
const samlRequestBody = format(samlRequestTemplate, `${uniqid()}.${currentDate}`, currentDate, ticket);

try {
const response = await axios.post(samlValidateUrl, samlRequestBody, {
headers: { 'Content-Type': 'text/xml' }
const response = await fetch(samlValidateUrl, {
method: 'POST',
headers: { 'Content-Type': 'text/xml' },
body: samlRequestBody
});
const casUser = await transform(response.data, samlResponseTemplate);
const data = await response.text();
const casUser = await transform(data, samlResponseTemplate);

return {
...casUser,
Expand Down
2 changes: 1 addition & 1 deletion ui/src/access/User.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MemberResult } from '@/services/GroupingsApiResults';
import { MemberResult } from '@/groupings/GroupingsApiResults';
import Role from './Role';

type User = {
Expand Down
File renamed without changes.
200 changes: 200 additions & 0 deletions ui/src/services/FetchService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
'use server';

import { ApiError } from '../groupings/GroupingsApiResults';
import { getCurrentUser } from '@/access/AuthenticationService';

const maxRetries = 3;
const baseUrl = process.env.NEXT_PUBLIC_API_2_1_BASE_URL as string;

/**
* Sleep/wait for the specified milliseconds.
*
* @param ms - the time in milliseconds to wait for
*
* @returns setTimeout promise
*/
const delay = async (ms = 5000) => new Promise((res) => setTimeout(res, ms));

/**
* Polls to getAsyncJobResult API endpoint until the async job has completed with a result.
*
* @param jobId - the jobId returned from the response of an async endpoint
*
* @returns The promise of type T or ApiError type
*/
const poll = async <T> (jobId: number): Promise<T & ApiError> => {
const currentUser = await getCurrentUser();
return fetch(`${baseUrl}/jobs/${jobId}`, { headers: { 'current_user': currentUser.uid } })
.then(res => res.json())
.then(async res => {
if (res.status === 'COMPLETED') {
return res.result;
}
await delay();
return poll<T>(jobId);
})
.catch(err => err);
};

/**
* Perform a GET request to the specified URL.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
*
* @returns The promise of type T or ApiError type
*/
export const getRequest = async <T> (
endpoint: string,
currentUserKey: string = ''
): Promise<T & ApiError> =>
await fetch(endpoint, { headers: { 'current_user': currentUserKey } })
.then(res => res.json())
.catch(err => err);

/**
* Perform a POST request to the specified URL.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
* @param body - the request body to perform the request with
*
* @returns The promise of type T or ApiError type
*/
export const postRequest = async <T> (
endpoint: string,
currentUserKey: string,
body?: string | string[],
): Promise<T & ApiError> =>
await fetch(endpoint, {
method: 'POST',
headers: { 'current_user': currentUserKey },
body: JSON.stringify(body)})
.then(res => res.json())
.catch(err => err);

/**
* Perform a POST request to the specified URL asynchronously using polling.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
* @param body - the request body to perform the request with
*
* @returns The promise of type T or ApiError type
*/
export const postRequestAsync = async <T> (
endpoint: string,
currentUserKey: string,
body: string | string[]
): Promise<T & ApiError> =>
await fetch(endpoint, { method: 'POST', headers: { 'current_user': currentUserKey }, body: JSON.stringify(body) })
.then(res => res.json())
.then(res => poll<T>(res))
.catch(err => err);

/**
* Perform a POST request to the specified URL with retries on error with incremental backoff.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
* @param body - the request body to perform the request with
*
* @returns The promise of type T or ApiError type
*/
export const postRequestRetry = async <T> (
endpoint: string,
currentUserKey: string,
body: string | string[],
retries: number = maxRetries
): Promise<T & ApiError> =>
await fetch(endpoint, { method: 'POST', headers: { 'current_user': currentUserKey }, body: JSON.stringify(body) })
.then(async res => {
if (res.status === 500 && retries > 0) {
await delay(2000 * Math.log(maxRetries / retries));
return postRequestRetry(endpoint, currentUserKey, body, retries - 1);
}
return res.json();
})
.catch(err => err);


/**
* Perform a PUT request to the specified URL.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
* @param body - the request body to perform the request with
*
* @returns The promise of type T or ApiError type
*/
export const putRequest = async <T> (
endpoint: string,
currentUserKey: string,
body?: string | string[]
): Promise<T & ApiError> =>
await fetch(endpoint, {
method: 'PUT',
headers: { 'current_user': currentUserKey },
body: JSON.stringify(body) })
.then(res => res.json())
.catch(err => err);

/**
* Perform a PUT request to the specified URL asynchronously using polling.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
* @param body - the request body to perform the request with
*
* @returns The promise of type T or ApiError type
*/
export const putRequestAsync = async <T> (
endpoint: string,
currentUserKey: string,
body: string | string[]
): Promise<T & ApiError> =>
await fetch(endpoint, { method: 'PUT', headers: { 'current_user': currentUserKey }, body: JSON.stringify(body) })
.then(res => res.json())
.then(res => poll<T>(res))
.catch(err => err);

/**
* Perform a DELETE request to the specified URL.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
* @param body - the request body to perform the request with
*
* @returns The promise of type T or ApiError type
*/
export const deleteRequest = async <T> (
endpoint: string,
currentUserKey: string,
body?: string | string[]
): Promise<T & ApiError> =>
await fetch(endpoint, { method: 'DELETE', headers: { 'current_user': currentUserKey }, body: JSON.stringify(body) })
.then(res => res.json())
.then(res => (res))
.catch(err => err);

/**
* Perform a DELETE request to the specified URL asynchronously using polling.
*
* @param endpoint - the URL to perform the request on
* @param currentUserKey - the uhIdentifier of the current user
* @param body - the request body to perform the request with
*
* @returns The promise of type T or ApiError type
*/
export const deleteRequestAsync = async <T> (
endpoint: string,
currentUserKey: string,
body?: string | string[]
): Promise<T & ApiError> =>
await fetch(endpoint, {
method: 'DELETE',
headers: { 'current_user': currentUserKey },
body: JSON.stringify(body) })
.then(res => res.json())
.then(res => poll<T>(res))
.catch(err => err);
Loading

0 comments on commit 2f24c9c

Please sign in to comment.