-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
125 lines (109 loc) · 3.92 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import express, { json } from 'express';
import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import chromium from '@sparticuz/chromium';
const __dirname = dirname(fileURLToPath(import.meta.url));
puppeteer.use(StealthPlugin());
const app = express();
app.use(json());
app.use(express.static('.'));
// Function to analyze a single URL
async function analyzeUrl(browser, url) {
try {
const page = await browser.newPage();
await page.setGeolocation({
latitude: 43.6532, // Toronto coordinates
longitude: -79.3832
});
await page.setUserAgent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) ' +
'Chrome/114.0.5735.198 Safari/537.36'
);
await page.setExtraHTTPHeaders({
'Accept-Language': 'en-US,en;q=0.9',
});
await page.setRequestInterception(true);
page.on('request', (request) => {
const resourceType = request.resourceType();
if (['image', 'media', 'stylesheet', 'font'].includes(resourceType)) {
request.abort(); // Block these resources
} else {
request.continue();
}
});
await page.goto(url, { waitUntil: 'load', timeout: 600000 });
// Inject the axe-core CDN script
await page.addScriptTag({
url: 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.4.1/axe.min.js'
});
const results = await page.evaluate(async () => {
// Ensure axe is available in the page context
if (!window.axe) throw new Error('axe-core not found on the page');
// Run axe analysis with specific rules and options (customize as needed)
return await window.axe.run({
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'best-practice'],
},
resultTypes: ['violations'],
iframes: false,
shadowDom: false,
});
});
return { url, violations: results.violations };
} catch (error) {
console.error(`Error during analysis of ${url}:`, error);
return { url, error: error.message };
}
}
async function analyzeMultipleUrls(urls) {
const browser = await puppeteer.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--ignore-certificate-errors',
'--ignore-certificate-errors-spki-list',
'--disable-gpu',
'--disable-dev-shm-usage',
],
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || '/app/.chrome-for-testing/chrome-linux64/chrome',
headless: true
});
const results = [];
try {
for (const url of urls) {
const result = await analyzeUrl(browser, url);
results.push(result);
}
} finally {
await browser.close();
}
return results;
}
// Endpoint to handle multiple URLs for accessibility analysis
app.post('/analyze-multiple', async (req, res) => {
const urls = req.body.urls;
if (!Array.isArray(urls) || urls.length === 0) {
res.json({ error: 'No URLs provided or invalid format.' });
return;
}
try {
// Analyze all URLs asynchronously
const results = await analyzeMultipleUrls(urls);
res.json({ results });
} catch (error) {
console.error('Error during analysis:', error);
res.json({ error: 'An error occurred during the analysis.' });
}
});
app.get('/', (req, res) => {
res.sendFile(join(__dirname, "index.html"));
});
// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});