Unity WebGL使用nginx作反向代理处理跨域,一些跨域的错误处理(添加了反向代理的配置依旧不能跨域)

反向代理与跨域描述

什么是跨域?

跨域(Cross-Origin Resource Sharing, CORS)是指在浏览器中,当一个网页的脚本试图从一个域名(协议、域名、端口)请求另一个域名的资源时,浏览器会阻止这种请求,除非目标服务器明确允许这种跨域请求。这是为了防止恶意网站通过脚本访问其他网站的资源,从而保护用户的安全。

跨域请求的三个条件

  1. 协议不同 :例如,httphttps 是不同的协议。
  2. 域名不同 :例如,example.comapi.example.com 是不同的域名。
  3. 端口不同 :例如,example.com:80example.com:443 是不同的端口。

只要这三个条件中有一个不同,就会触发跨域问题。

为什么要用nginx反向代理解决跨域问题?

nginx是exe,不是前端的网页不会受到同源策略的影响,所以可以使用nginx反向代理解决跨域。

前端程序将请求发送给nginx,nginx获取到请求的URL会根据配置文件将请求的URL进行转发,收到数据后再返回给前端。

效果展示

代码描述

在nginx中添加配置文件

js 复制代码
          location /api/ {
               proxy_pass http://t.weather.itboy.net;
               add_header 'Access-Control-Allow-Origin' '*';
               add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
               add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
           }

服务配置

js 复制代码
    server {
    listen       58231;
    server_name  localhost;

nginx会处理对localhost:58231的请求,然后进行匹配,如果是localhost:58231/api/ 的请求则会将请求转发给
http://t.weather.itboy.net ,所以在前端发送的请求的地址应该是nginx的地址, const response = await fetch('http://localhost:58231/api/weather/city/101030100');

在unity的代码中是使用配置文件,需要在StreamingAssets 中创建一个txt,名称是request_url,内容是请求的URL:http://localhost:58231/api/weather/city/101030100 。 然后会发送请求到nginx,nginx根据反向代理配置将请求转发到真正的服务器。

错误处理

已经添加了proxy_pass 配置但是还是提示不能跨域或者404/502

  1. proxy_pass 后面没有斜杠

    • 如果 proxy_pass 后面没有斜杠,Nginx 会将匹配的 location 路径附加到 proxy_pass 的 URL 后面。

    • 举个例子:

      nginx 复制代码
      location /api/ {
          proxy_pass http://t.weather.itboy.net;
      }

      当你访问 http://localhost:58231/api/weather/city/101030100 时,Nginx 会将请求转发到 http://t.weather.itboy.net/api/weather/city/101030100

  2. proxy_pass 后面有斜杠

    • 如果 proxy_pass 后面有斜杠,Nginx 会将匹配的 location 路径替换为 proxy_pass 的 URL。

    • 举个例子:

      nginx 复制代码
      location /api/ {
          proxy_pass http://t.weather.itboy.net/;
      }

      当你访问 http://localhost:58231/api/weather/city/101030100 时,Nginx 会将请求转发到 http://t.weather.itboy.net/weather/city/101030100。所以就不可访问就404了。

测试网站

一个可以使用get请求获取假数据的网站,网站本身是支持跨域的,所以不配置nginx也可以进行通信。

js 复制代码
https://jsonplaceholder.typicode.com/

一个天气预报的API,可以进行get请求的测试

js 复制代码
http://t.weather.itboy.net/api/weather/city/101030100

相关代码

Nginx配置

复制代码
 worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       58231;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

        location /api/ {
        #  将http://t.weather.itboy.net 替换为实际的服务器
            proxy_pass http://t.weather.itboy.net;
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        }

        # On-disk Brotli-precompressed data files should be served with compression enabled:
        location ~ .+\.(data|symbols\.json)\.br$ {
            gzip off;
            add_header Content-Encoding br;
            default_type application/octet-stream;
        }

        # On-disk Brotli-precompressed JavaScript code files:
        location ~ .+\.js\.br$ {
            gzip off;
            add_header Content-Encoding br;
            default_type application/javascript;
        }

        # On-disk Brotli-precompressed WebAssembly files:
        location ~ .+\.wasm\.br$ {
            gzip off;
            add_header Content-Encoding br;
            default_type application/wasm;
        }

        # On-disk gzip-precompressed data files should be served with compression enabled:
        location ~ .+\.(data|symbols\.json)\.gz$ {
            gzip off;
            add_header Content-Encoding gzip;
            default_type application/octet-stream;
        }

        # On-disk gzip-precompressed JavaScript code files:
        location ~ .+\.js\.gz$ {
            gzip off;
            add_header Content-Encoding gzip;
            default_type application/javascript;
        }

        # On-disk gzip-precompressed WebAssembly files:
        location ~ .+\.wasm\.gz$ {
            gzip off;
            add_header Content-Encoding gzip;
            default_type application/wasm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

Unity代码

复制代码
using Best.HTTP;
using Cysharp.Threading.Tasks;
using System;
using UnityEngine;
using UnityEngine.Networking;

public class SendGetR : MonoBehaviour
{
    private string requestUrlFilePath = Application.streamingAssetsPath + "/request_url.txt";

    async void Start()
    {
        Debug.Log("开始发送请求啦!");
        string fileContent = await ReadFileAsync(requestUrlFilePath);
        await GetObtainCodingRulesAsync(fileContent);
    }

    /// <summary>
    /// 异步读取文件内容
    /// </summary>
    /// <param name="filePath">文件路径</param>
    /// <returns>文件内容</returns>
    public async UniTask<string> ReadFileAsync(string _filePath)
    {
        try
        {
            using (UnityWebRequest uwr = UnityWebRequest.Get(_filePath))
            {
                await uwr.SendWebRequest();
                Debug.Log("请求到的URL是:" + uwr.downloadHandler.text);
                return uwr.downloadHandler.text;
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError("读取文件失败: " + e.Message);
            return null;
        }
    }

    /// <summary>
    /// 异步获取赋码规则
    /// </summary>
    /// <param name="url">请求的URL</param>
    /// <returns>赋码规则列表</returns>
    public async UniTask<string> GetObtainCodingRulesAsync(string _url)
    {
        try
        {
            var request = new HTTPRequest(new System.Uri(_url), HTTPMethods.Get, (req, res) =>
            {
                if (res.IsSuccess)
                {
                    Debug.Log("返回的数据是:" + res.DataAsText);
                }
                else
                {
                    Debug.Log("发送失败tmp_requestURL: " + _url);
                }
            });
            await request.Send();
            await UniTask.WaitUntil(() => request.Response.DataAsText != null);
            return request.Response.DataAsText;
        }
        catch (Exception e)
        {
            Debug.LogError($"发送失败: {e.Message}");
        }

        return "没有获取到数据";
    }
}

测试使用html代码

复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>发送GET请求</title>
</head>

<body>
  <h1>发送GET请求到CSDN</h1>
  <p>请点击按钮发送请求,并在浏览器控制台查看结果。</p>

  <!-- 添加一个按钮 -->
  <button id="sendRequestButton">发送请求</button>

  <script>
    // 发送GET请求的函数
    async function sendGetRequest() {
      try {
        // 发送GET请求到你的Nginx服务器
        const response = await fetch('http://localhost:58231/api/weather/city/101030100');

        // 检查响应状态
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        // 读取响应内容
        const data = await response.text();

        // 在控制台中显示响应内容
        console.log('Response status:', response.status);
        console.log('Response data:', data);
      } catch (error) {
        // 捕获并显示错误
        console.error('Error:', error);
      }
    }

    // 获取按钮元素
    const button = document.getElementById('sendRequestButton');

    // 为按钮添加点击事件监听器
    button.addEventListener('click', sendGetRequest);
  </script>
</body>

</html>

Enjoy Life

相关推荐
XIAOHEZIcode20 小时前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220702 天前
如何搭建本地yum源(上)
运维
一颗烂土豆2 天前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
ping某3 天前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
大树884 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质4 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工5 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智5 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_5 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化