Skip to content

Instantly share code, notes, and snippets.

@IvanAdmaers
Created November 23, 2022 20:22
Show Gist options
  • Save IvanAdmaers/d333595b56a88ffd94737c9fb05c7f09 to your computer and use it in GitHub Desktop.
Save IvanAdmaers/d333595b56a88ffd94737c9fb05c7f09 to your computer and use it in GitHub Desktop.
Check is an image available by its url
import fs from 'fs/promises';
import path from 'path';
import axios from 'axios';
import { checkImageUrl, allowedFormats, requestWaitingTimeInMs } from '..';
jest.useFakeTimers();
describe('checkImageUrl', () => {
it('should return a correct result for jpeg', async () => {
const isAllowed = allowedFormats.includes('jpeg');
const jpegImageBuffer = await fs.readFile(
path.join(__dirname, './images/jpeg-test.jpeg')
);
const mockGet = jest.spyOn(axios, 'get');
mockGet.mockImplementation(() =>
Promise.resolve({ data: jpegImageBuffer })
);
const result = await checkImageUrl('https://tsthisisforyoudear.com/');
expect(result).toBe(isAllowed);
});
it('should return a correct result for webp', async () => {
const isAllowed = allowedFormats.includes('webp');
const webpImageBuffer = await fs.readFile(
path.join(__dirname, './images/webp-test.webp')
);
const mockGet = jest.spyOn(axios, 'get');
mockGet.mockImplementation(() =>
Promise.resolve({ data: webpImageBuffer })
);
const result = await checkImageUrl('https://tsthisisforyoudear.com/');
expect(result).toBe(isAllowed);
});
it('should return null when server not responding', () => {
const mockGet = jest.spyOn(axios, 'get');
mockGet.mockImplementation(() => new Promise(() => {}));
const pendingPromise = checkImageUrl(
'https://tsthisisforyoudear.com/'
).then((result) => {
expect(result).toBe(null);
});
jest.advanceTimersByTime(requestWaitingTimeInMs);
return pendingPromise;
});
});
import axios from 'axios';
import AbortController from 'abort-controller';
import FileType from 'file-type';
export const allowedFormats = ['jpg', 'jpeg', 'png'];
export const requestWaitingTimeInMs = 3 * 1000;
/**
* This function checks does an image available by url
*/
export const checkImageUrl = async (url: string): Promise<boolean | null> =>
new Promise((resolve) => {
try {
(async () => {
const controller = new AbortController();
const { signal } = controller;
const timeout = setTimeout(() => {
controller.abort();
}, requestWaitingTimeInMs);
signal.addEventListener('abort', () => {
console.log(
`Request to URL ${url} cancelled due to server not responding`
);
resolve(null);
});
const req = await axios.get(url, {
responseType: 'arraybuffer',
signal,
});
clearTimeout(timeout);
const buffer = Buffer.from(req.data, 'binary');
const fileData = await FileType.fromBuffer(buffer);
const { ext, mime } = fileData ?? {};
if (ext === undefined || mime === undefined) {
return resolve(false);
}
const fileType = mime.split('/')[0];
if (fileType !== 'image') {
return resolve(false);
}
if (allowedFormats.includes(ext) === false) {
return resolve(false);
}
return resolve(true);
})();
} catch (error) {
console.error(error);
return resolve(null);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment