Spaces:
Sleeping
Sleeping
import express from 'express'; | |
import cors from 'cors'; | |
const app = express(); | |
const PORT = process.env.PORT || 7860; | |
app.use((req, res, next) => { | |
console.log("before", req.method, req.originalUrl); | |
next(); | |
}); | |
app.use((req, res, next) => { | |
res.setHeader('Access-Control-Max-Age', 86400); | |
next(); | |
}); | |
// 解析 JSON body | |
app.use(express.json()); | |
// --- CORS 配置 --- | |
// 允许任何方法和标准的请求头 | |
const corsOptions = { | |
origin: '*', | |
methods: '*', // 允许所有 HTTP 方法 | |
allowedHeaders: '*', | |
exposedHeaders: '*', | |
maxAge: 10, // 10 秒内不重复预检请求 | |
}; | |
app.use(cors(corsOptions)); | |
// 自定义中间件,添加一个测试用的响应头 | |
app.use((req, res, next) => { | |
res.setHeader('X-Custom-Header-Test', 'HuggingFace-Express-App-Works'); | |
res.setHeader('Access-Control-Max-Age', 86400); | |
next(); | |
}); | |
// --- 中间件和路由 --- | |
// 使用 app.all() 捕获所有方法的 /api 请求 | |
app.all('/api', (req, res) => { | |
console.log(req.method, res.getHeader('Access-Control-Max-Age')); | |
res.json({ | |
message: `API is working! Request received with method: ${req.method}.`, | |
methodUsed: req.method, // 在响应中明确指出收到的方法 | |
bodyReceived: req.body, // 如果有请求体,也一并返回 | |
timestamp: new Date().toISOString(), | |
}); | |
}); | |
// 根路由,返回一个静态 HTML 骨架,由客户端 JS 填充内容 | |
app.get('/', (req, res) => { | |
res.send(` | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Express App on Hugging Face</title> | |
<style> | |
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; padding: 2em; background-color: #f9fafb; color: #111827; } | |
.container { max-width: 800px; margin: auto; background: white; padding: 2em; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); } | |
h1 { color: #1f2937; } | |
p { font-size: 1.1em; } | |
pre { background-color: #f3f4f6; padding: 1.5em; border-radius: 8px; white-space: pre-wrap; word-wrap: break-word; min-height: 150px; cursor: pointer; } | |
code { font-family: "Courier New", Courier, monospace; font-size: 1.1em; } | |
.copy-notice { font-size: 0.9em; color: #6b7280; margin-top: 1em; text-align: center; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>Express.js App Deployed</h1> | |
<p>Please copy the following dynamically generated <code>fetch</code> POST request code into your browser's developer console to test:</p> | |
<pre><code id="fetch-code"><!-- Code will be dynamically populated here by JS --></code></pre> | |
<p class="copy-notice">Click the code block above to copy.</p> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', () => { | |
const codeElement = document.getElementById('fetch-code'); | |
const origin = window.location.origin; | |
// 注意:这里的反斜杠是必需的,因为这段JS代码本身是位于一个父模板字符串中 | |
const fetchCode = \`fetch('\${origin}/api', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify({ user: 'test-user', action: 'check-cors' }) | |
}) | |
.then(response => { | |
console.log('Status:', response.status); | |
console.log('Custom Header "X-Custom-Header-Test":', response.headers.get('X-Custom-Header-Test')); | |
return response.json(); | |
}) | |
.then(data => console.log('Data:', data)) | |
.catch(error => console.error('Error:', error));\`; | |
codeElement.textContent = fetchCode; | |
}); | |
document.querySelector('pre').addEventListener('click', function() { | |
const codeToCopy = document.getElementById('fetch-code').innerText; | |
navigator.clipboard.writeText(codeToCopy).then(() => { | |
alert('Code copied to clipboard!'); | |
}).catch(err => { | |
console.error('Failed to copy: ', err); | |
}); | |
}); | |
</script> | |
</body> | |
</html> | |
`); | |
}); | |
app.listen(PORT, () => { | |
console.log(`Server is running at http://localhost:${PORT}`); | |
}); |