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

先生沉默先 2024-10-20 08:33:01 阅读 53

反向代理与跨域描述

什么是跨域?

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

跨域请求的三个条件

协议不同:例如,<code>http 和 https 是不同的协议。域名不同:例如,example.comapi.example.com 是不同的域名。端口不同:例如,example.com:80example.com:443 是不同的端口。

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

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

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

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

效果展示

在这里插入图片描述

代码描述

在nginx中添加配置文件

<code> 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';

}

服务配置

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

proxy_pass 后面没有斜杠

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

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

proxy_pass 后面有斜杠

如果 proxy_pass 后面有斜杠,Nginx 会将匹配的 location 路径替换为 proxy_pass 的 URL。举个例子:

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也可以进行通信。

https://jsonplaceholder.typicode.com/

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

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>code>

/// <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>code>

/// <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">code>

<head>

<meta charset="UTF-8">code>

<meta name="viewport" content="width=device-width, initial-scale=1.0">code>

<title>发送GET请求</title>

</head>

<body>

<h1>发送GET请求到CSDN</h1>

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

<!-- 添加一个按钮 -->

<button id="sendRequestButton">发送请求</button>code>

<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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。