问题简介: 用Hbuilder开发uniapp 的 h5项目时,运行到外部谷歌浏览器chrome进行调试,当后台使用打印命令如dd('123),在开发者工具devtool的preview内看不到调试或打印信息,提示跨域,这样用chrome不方便调试,我在后端nginx配置跨域设置后依然不行,这是为什么,如何解决?
特别情况 如果运行到Hbuider内置浏览器时在开发者工具的preview可以正常输出'123'),且只要去掉dd()打印标签后,接口访问正常的,200状态码下chrome运行是正常的,没有跨域的报错。
当后台用dd('123),时,前端提示500状态,且报错截图如下:
localhost/:1 Access to XMLHttpRequest at 'http://a.b.c/api/index' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
在hbiuderx 的内置浏览器运行后,可以看到preview 和response都可以显示后端打印的值:
问题背景:前端是h5版,uniapp项目,后台是php环境,macos、mamp开发环境,
前端h5地址:http://localhost:8080/
后台服务器接口地址:http://a.b.c/api/index
nginx跨域配置:
location /api {
add_header 'Access-Control-Allow-Origin' 'http://localhost:8080';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Credentials' 'false';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Data-Type,X-Requested-With,X-Data-Type,X-Auth-Token,X-Api-Key,Merchant-Id,Device-id,Device-Name,Width,Height,Os,Os-Version,Is-Root,Network,Wifi-Ssid,Wifi-Mac,Xyz,Version-Name,Api-Version,Channel,App-Name,Dpi,Api-Level,Operator,Idfa,Idfv,Open-Udid,Wlan-Ip,Time';
add_header 'Access-Control-Expose-Headers' 'Content-Disposition,XMLHttpRequest';
add_header 'Content-Disposition' 'attachment';
try_files $uri $uri/ /api/index.php$is_args$args;
}
参考GPT和自己的思路:这个问题是由于浏览器的同源策略导致的,即浏览器不允许来自不同源的脚本访问同一页面的内容。在这种情况下,你需要在服务器端配置CORS(跨域资源共享)来允许来自不同源的请求。
根据你提供的信息,你已经在nginx中添加了CORS配置,但是这似乎没有解决问题。这可能是因为CORS配置不正确或未正确生效。
你可以尝试使用浏览器的开发者工具来检查请求的响应头,以查看是否正确设置了CORS头。如果CORS头正确设置,则应该包含“Access-Control-Allow-Origin”和其他指定的CORS头。
如果CORS头未正确设置,请检查你的nginx配置并确保已正确设置。此外,确保服务器端代码不会覆盖你在nginx中设置的CORS头。
此外,你还可以尝试使用其他跨域解决方案,如JSONP或代理服务器,以解决此问题。
从你提供的信息来看,nginx的跨域配置似乎是正确的,但你可以尝试进行一些修改,以进一步排除问题。
1 修改CORS配置中的Access-Control-Allow-Origin值:
将配置中的'Access-Control-Allow-Origin' 'http://localhost:8080'修改为'*',表示允许来自任何域的请求。
2 添加OPTIONS请求的CORS配置:
由于浏览器会发送一个OPTIONS请求来验证是否允许跨域访问,因此你需要添加OPTIONS请求的CORS配置。你可以在配置中添加以下内容:
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Credentials' 'false';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Data-Type,X-Requested-With,X-Data-Type,X-Auth-Token,X-Api-Key,Merchant-Id,Device-id,Device-Name,Width,Height,Os,Os-Version,Is-Root,Network,Wifi-Ssid,Wifi-Mac,Xyz,Version-Name,Api-Version,Channel,App-Name,Dpi,Api-Level,Operator,Idfa,Idfv,Open-Udid,Wlan-Ip,Time';
add_header 'Access-Control-Expose-Headers' 'Content-Disposition,XMLHttpRequest';
add_header 'Content-Disposition' 'attachment';
return 200;
}
这将允许来自任何域的OPTIONS请求,并添加所需的CORS头。
3 检查nginx配置文件中是否存在其他与CORS相关的配置,以确保它们不会覆盖你的CORS配置。
你可以通过检查nginx配置文件中是否存在类似于proxy_set_header Access-Control-Allow-Origin的配置来确认这一点。如果找到类似的配置,请将其删除或注释掉。
请注意,以上修改可能不一定适用于所有情况,因此请根据自己的情况进行适当的调整。同时,确保在修改nginx配置文件时备份原始文件,以便出现问题时可以恢复原始配置。
“Devil组”引证GPT后的撰写:
在PHP代码中使用header()函数来设置CORS响应头。以下是一个示例代码:
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: Authorization, Content-Type, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, X-Data-Type, X-Requested-With, X-Data-Type, X-Auth-Token, X-Api-Key, Merchant-Id, Device-id, Device-Name, Width, Height, Os, Os-Version, Is-Root, Network, Wifi-Ssid, Wifi-Mac, Xyz, Version-Name, Api-Version, Channel, App-Name, Dpi, Api-Level, Operator, Idfa, Idfv, Open-Udid, Wlan-Ip, Time");
header("Access-Control-Expose-Headers: Content-Disposition, XMLHttpRequest");
header("Content-Disposition: attachment");
将上述代码添加到PHP代码中,并根据实际需要修改"Access-Control-Allow-Origin"等相关CORS头的值,然后重新运行项目测试是否能正常输出调试信息。
有个很简单那的办法,你用postman对你那个后端接口发起请求,如果是跨域的话,一般会提示的。
如果你很确定是跨域问题,直接在laravel里面加一个中间件,让他对你的ip设置不跨域就好l
public function handle($request, Closure $next)
{
$response = $next($request);
$origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : '';
$allow_origin = [
'http://localhost:8000',
];
if (in_array($origin, $allow_origin)) {
$response->header('Access-Control-Allow-Origin', $origin);
$response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, X-CSRF-TOKEN, Accept, Authorization, X-XSRF-TOKEN');
$response->header('Access-Control-Expose-Headers', 'Authorization, authenticated');
$response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS');
$response->header('Access-Control-Allow-Credentials', 'true');
}
return $response;
}
配置下跨域, 配置好了要重启、
在 manifest.json
中添加如下配置
"h5" : {
"devServer" : {
"proxy" : {
"/api" : {
"target" : "http://a.b.c/",
"pathRewrite" : {
"^/api" : "/api"
}
}
}
}
}