Spaces:
Sleeping
Sleeping
File size: 1,609 Bytes
17c92f2 |
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 |
const express = require('express');
const fetch = require('node-fetch');
const cheerio = require('cheerio');
const { URL } = require('url');
const app = express();
const PORT = 7860;
function absolutize(base, relative) {
try {
return new URL(relative, base).toString();
} catch {
return relative;
}
}
app.get('/proxy', async (req, res) => {
const targetUrl = req.query.url;
if (!targetUrl) {
return res.status(400).send('Missing ?url= parameter');
}
try {
const response = await fetch(targetUrl);
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('text/html')) {
const html = await response.text();
const $ = cheerio.load(html);
const base = targetUrl;
// 書き換える属性
const attributes = ['href', 'src', 'action'];
$('*').each((i, el) => {
attributes.forEach(attr => {
const val = $(el).attr(attr);
if (val && !val.startsWith('data:') && !val.startsWith('javascript:')) {
const abs = absolutize(base, val);
$(el).attr(attr, `/proxy?url=${encodeURIComponent(abs)}`);
}
});
});
res.set('Content-Type', 'text/html');
res.send($.html());
} else {
// HTML以外はそのままパイプ
res.set('Content-Type', contentType);
response.body.pipe(res);
}
} catch (err) {
console.error(err);
res.status(500).send('プロキシエラー: ' + err.message);
}
});
app.listen(PORT, () => {
console.log(`🌐 Proxy server running at http://localhost:${PORT}`);
});
|