Files
CJGIS_UAVPatrol/server/http.js
❀ » Cato Sweeney. ❀ » Console@the.bb bb46cb3bcc *
2025-11-27 16:14:04 +08:00

205 lines
8.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// http.js 的 main 函数是http服务的所有脚本函数执行的预处理入口
function main() {
// 当前时间
let time = new Date()
let timeStr = time.toUTCString()
response.headers.set("Date", timeStr)
payload.set.header("Timestamp", time.getTime())
// 安全性检查
'use api/lib/sourceAnti.js'
'use api/lib/setResponseHeaders.js'
let req = payload.get()
if (!req?.headers['Cache-Control'] || !req?.headers['Cache-Control']['skip-cache']) {
// 从Header、Query、Cookie、Body中获取token
let userToken = req?.headers?.Authorization || req?.query?.token || req?.headers["X-Token"] || req?.cookie?.token
var signature = `${req.method}:${req.host}:${req.url}::${req.url}:${userToken}:${req.body ? req.body.toString() : '>'}`
signature = crypto.hash.md5(signature).toHEX.encoding().toString()
// 缓存5秒 - 缓存命中则直接返回
let cacheData = cache.get('results', signature)
if (cacheData && cacheData != '') {
response.contentType.json()
response.headers.set("Cache-Status", "hit")
response.headers.set("Cache-Key", signature)
// 如果请求头中包含 Accept-Encoding 并且 Accept-Encoding 的值包含 br则设置 Content-Encoding 为 br。
if (req.headers['Accept-Encoding'] && req.headers['Accept-Encoding'][0].includes('br')) {
response.headers.set("Content-Encoding", 'br')
}
var currentTime = new Date();
let timeDiff = currentTime - time
response.headers.set("Server-Timing", `RequestCost;dur=${timeDiff}`)
// currentTime.setSeconds(currentTime.getSeconds() + 5);
// var timeAfter = currentTime.toUTCString();
// response.headers.set("Expires", timeAfter)
response.headers.set("Cache-Control", `no-transform,no-siteapp,max-age=5`)
response.write(cacheData)
return
}
}
// 声明路径
let filePath = req.path.substring(1)
// 如果Header加上Cache-Control:*则移除缓存,本次访问将不会命中缓存,有刷新效果。
if (req?.headers['Cache-Control'] && req?.headers['Cache-Control']['clear']) {
runtime.cache.remove(filePath)
response.headers.set("Clear-Site-Data", '"*"')
}
switch (req.method) {
case 'OPTIONS':
// 这样对于所有的 OPTIONS 请求都会返回 200 (OK) 状态码
response.status.ok()
return
// 当接收的请求为 GET 时
case 'GET':
// 特殊访问路径
// JWK
if (filePath == '.well-known/jwks.json') {
response.contentType.json()
response.write(`{"keys":[{"kty":"SM2","e":"AQAB","n":"${SYSTEM_CONFIG.find(item => item.name === 'system_jwt_public').value.replace(/--.*\n/, "").replace(/\n.*--/, "")}","alg":"SS256","use":"sig","kid":"${ex.suid().base58()}"}]}`)
return
}
// 【安全须知】
// 原则上所有命名以.和_开头的目录或文件都不允许直接被访问
// 因为它们很大概率是系统文件或非开放文件
if (!filePath.startsWith('.well-known') && (filePath.startsWith('.') || filePath.startsWith('_'))) {
response.status.code(404)
return `404 page not found`
}
// 可访问的脚本路径
let allowScriptPath = [
'static/index.js',
'static/js/md5.js',
]
// 【安全须知】
// 原则上所有的js文件都不允许直接被访问以免源代码泄露所以返回404。
// 如果需要将js对外暴露请在allowScriptPath中添加。
// 但app目录内的所有js文件除外因为该目录用于放置前端页面
if (filePath.endsWith('.js') && !filePath.startsWith('app') && !allowScriptPath.includes(filePath)) {
response.status.code(404)
return `404 page not found`
}
response.headers.set("Content-Type", "text/html; charset=utf-8;");
// 判断是否为目录以及否存在index.html或index.html文件如果存在则返回index.html或index.htm文件
if (filePath[filePath.length - 1] == "/" || filePath == "" || fs.isDir(filePath)) {
if (filePath == "") {
filePath = rootPath
}
let tmp = fs.join(filePath, 'index.htm')
if (fs.exists(tmp)) {
filePath = tmp
response.file(filePath)
return
}
tmp += "l"
if (fs.exists(tmp)) {
filePath = tmp
response.file(filePath)
return
}
}
// 获取文件类型
'use api/lib/getFileMimeType.js'
response.headers.set('Content-Type', getFileMimeType(filePath))
// 如果不是目录,则尝试返回文件
if (fs.exists(filePath) && !fs.isDir(filePath)) {
const fileSqlPath = req.path
if (fileSqlPath.includes('/uploads/')) {
// 查询数据库中是否有该文件的信息
const file_info = SQL.query('system_sql', 'SELECT * FROM sys_files WHERE file_id = ?', req.path.split("/").pop())
if (file_info.length > 0) {
// 判断文件是否已删除
if (file_info[0].delete_time) {
return errMsg(404, '文件已删除')
}
filePath = rootPath + file_info[0].file_path
response.headers.add('X-File-Id', file_info[0].file_id)
response.headers.add('X-File-Name', file_info[0].file_name)
response.headers.add('X-File-Size', file_info[0].file_size)
response.headers.add('X-File-Owner', file_info[0].user_id)
response.headers.add('X-File-Create-Date', file_info[0].create_time)
response.headers.set('Content-Type', file_info[0].file_type)
// 设置 Content-Disposition
response.headers.set('Content-Disposition', 'filename=' + file_info[0].file_name)
}
}
if (req.query.download) {
// 设置 Content-Disposition
response.headers.add('Content-Disposition', 'attachment')
}
var currentTime = new Date();
let timeDiff = currentTime - time
response.headers.set("Server-Timing", `RequestCost;dur=${timeDiff}`)
// 如果文件存在,则返回文件
response.file(filePath)
return
}
}
// 默认情况下返回的内容都是JSON格式的所以在这里预设 Content-Type 为 application/json
response.headers.set("Content-Type", "application/json; charset=utf-8;");
// 声明缓存
response.headers.set(
'Cache-Control',
'no-transform,no-cache,immutable'
)
// payload.set.header('Signet', '/__/vlan/')
//
// 判断filePath存在则将请求移交给 filePath 下的 function.js 进行处理。
if (fs.exists(filePath)) {
runtime.goto(filePath, ...args)
return
}
// 如果不存在则尝试调用filepath的上一级目录下的function.js
// const parentDir = filePath.substr(0, filePath.lastIndexOf('/'))
runtime.goto(findValidPath(filePath), ...args) // goto会将 return 的内容写到 response.body 里面。但call不会。
return
}
// 递归路径
cache.new('route-path')
function findValidPath(filePath) {
// 尝试从缓存获取
const cachedPath = cache.get('route-path', filePath);
if (cachedPath) return cachedPath;
// 自上而下查找最深的有效路径
const pathParts = filePath.split('/').filter(Boolean);
let currentPath = '';
for (const part of pathParts) {
const testPath = currentPath ? fs.join(currentPath, part) : part;
if (!fs.exists(testPath)) break;
currentPath = testPath;
}
const result = currentPath || './';
// 缓存结果
cache.set('route-path', filePath, result, 60 * 1000); // 60秒缓存
return result;
}