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

相关推荐
木子Linux5 分钟前
【Linux打怪升级记 | 问题01】安装Linux系统忘记设置时区怎么办?3个方法教你回到东八区
linux·运维·服务器·centos·云计算
mit6.82411 分钟前
Ubuntu 系统下性能剖析工具: perf
linux·运维·ubuntu
watermelonoops20 分钟前
Windows安装Ubuntu,Deepin三系统启动问题(XXX has invalid signature 您需要先加载内核)
linux·运维·ubuntu·deepin
阿甘知识库42 分钟前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
saynaihe1 小时前
安全地使用 Docker 和 Systemctl 部署 Kafka 的综合指南
运维·安全·docker·容器·kafka
汪洪墩2 小时前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
zhou周大哥3 小时前
linux 安装 ffmpeg 视频转换
linux·运维·服务器
loong_XL3 小时前
服务器ip:port服务用nginx 域名代理
服务器·tcp/ip·nginx
m0_748234343 小时前
webGL硬核知识:图形渲染管渲染流程,各个阶段对应的API调用方式
图形渲染·webgl
the丶only4 小时前
单点登录平台Casdoor搭建与使用,集成gitlab同步创建删除账号
linux·运维·服务器·docker·gitlab