Spaces:
Sleeping
Sleeping
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}`); | |
}); | |