server.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**
  2. * 本地开发服务器,解决跨域问题
  3. *
  4. * 使用方法:node server.js
  5. * 启动后访问:http://localhost:3000/yuyue.html?test=1
  6. */
  7. const http = require('http')
  8. const fs = require('fs')
  9. const path = require('path')
  10. const url = require('url')
  11. const PORT = 3003
  12. const API_HOST = '61.164.207.46'
  13. const API_PORT = 8000
  14. const MIME = {
  15. '.html': 'text/html;charset=utf-8',
  16. '.js': 'application/javascript;charset=utf-8',
  17. '.css': 'text/css;charset=utf-8',
  18. '.json': 'application/json;charset=utf-8',
  19. '.png': 'image/png',
  20. '.jpg': 'image/jpeg',
  21. '.gif': 'image/gif',
  22. '.svg': 'image/svg+xml',
  23. '.ico': 'image/x-icon'
  24. }
  25. // 静态文件服务
  26. function serveStatic(req, res) {
  27. var pathname = url.parse(req.url).pathname
  28. if (pathname === '/') pathname = '/yuyue.html'
  29. var filePath = path.join(__dirname, pathname)
  30. var ext = path.extname(filePath)
  31. fs.readFile(filePath, function(err, data) {
  32. if (err) {
  33. res.writeHead(404, { 'Content-Type': 'text/plain' })
  34. res.end('Not Found')
  35. return
  36. }
  37. res.writeHead(200, {
  38. 'Content-Type': MIME[ext] || 'application/octet-stream',
  39. // 允许页面被 iframe 嵌入
  40. 'X-Frame-Options': 'SAMEORIGIN'
  41. })
  42. res.end(data)
  43. })
  44. }
  45. // 代理 API 请求
  46. function proxyApi(req, res) {
  47. var chunks = []
  48. req.on('data', function(chunk) { chunks.push(chunk) })
  49. req.on('end', function() {
  50. var body = Buffer.concat(chunks)
  51. // 从请求的 Host 头中获取域名和端口号
  52. var host = req.headers.host || (API_HOST + ':' + API_PORT)
  53. var hostParts = host.split(':')
  54. var targetHost = hostParts[0]
  55. var targetPort = hostParts[1] || '80'
  56. var options = {
  57. hostname: targetHost,
  58. port: targetPort,
  59. path: '/yos/rest/index',
  60. method: 'POST',
  61. headers: {
  62. 'Content-Type': 'application/json;charset=utf-8',
  63. 'Content-Length': body.length
  64. }
  65. }
  66. var proxyReq = http.request(options, function(proxyRes) {
  67. var data = []
  68. proxyRes.on('data', function(chunk) { data.push(chunk) })
  69. proxyRes.on('end', function() {
  70. // 返回响应,添加 CORS 头
  71. res.writeHead(proxyRes.statusCode, {
  72. 'Content-Type': 'application/json;charset=utf-8',
  73. 'Access-Control-Allow-Origin': '*',
  74. 'Access-Control-Allow-Methods': 'POST, OPTIONS',
  75. 'Access-Control-Allow-Headers': 'Content-Type'
  76. })
  77. res.end(Buffer.concat(data))
  78. })
  79. })
  80. proxyReq.on('error', function(err) {
  81. res.writeHead(500, { 'Content-Type': 'application/json;charset=utf-8' })
  82. res.end(JSON.stringify({ code: -1, data: '代理请求失败: ' + err.message }))
  83. })
  84. proxyReq.write(body)
  85. proxyReq.end()
  86. })
  87. }
  88. var server = http.createServer(function(req, res) {
  89. var pathname = url.parse(req.url).pathname
  90. // 处理 OPTIONS 预检请求
  91. if (req.method === 'OPTIONS') {
  92. res.writeHead(204, {
  93. 'Access-Control-Allow-Origin': '*',
  94. 'Access-Control-Allow-Methods': 'POST, OPTIONS',
  95. 'Access-Control-Allow-Headers': 'Content-Type',
  96. 'Access-Control-Max-Age': 86400
  97. })
  98. res.end()
  99. return
  100. }
  101. // API 代理
  102. if (pathname === '/api/proxy') {
  103. proxyApi(req, res)
  104. return
  105. }
  106. // 静态文件
  107. serveStatic(req, res)
  108. })
  109. server.listen(PORT, '0.0.0.0', function() {
  110. console.log('========================================')
  111. console.log(' 本地开发服务器已启动')
  112. console.log(' 访问地址: http://localhost:' + PORT + '/yuyue.html')
  113. console.log(' 测试模式: http://localhost:' + PORT + '/yuyue.html?test=1')
  114. console.log(' 按 Ctrl+C 停止')
  115. console.log('========================================')
  116. })