AJAX 没有来自 Grafana 的回复
No response from Grafana via AJAX
我在 Docker 容器中设置了 Grafana(来自 Docker 存储库的 grafana/grafana
图像),端口 3000 转发到我的本地主机。我的 docker-compose.yml
下面:
version: '2.1'
services:
grafana:
image: grafana/grafana
ports:
- 3000:3000
最初我也有 link 到 Graphite 和一些卷和环境配置(仅 GF_SECURITY_ADMIN_PASSWORD
),但我想这无关紧要。
我可以通过简单的 curl
调用从 Grafana 获得响应:
$ curl http://localhost:3000
<a href="/login">Found</a>.
但是当我试图通过 AJAX 调用获取它时,它给了我一个奇怪的结果:
$.ajax({url: 'http://localhost:3000', beforeSend: function(xhr, settings) {alert('before setting header'); xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); alert('after setting header');}});
[many JSON fields]
responseText:""
[many JSON fields]
statusText: "error"
[many JSON fields]
警报显示 header 已设置为接受来自任何来源的请求。
当我直接调用 Docker 容器地址时,也会发生同样的情况(curl 有效但 ajax 无效)。
后台发生了什么?为什么第二个请求不起作用?如何通过 AJAX 调用从 Grafana 获得响应?
问题是默认情况下 CORS 在 grafana 上未启用。 curl 请求不会检查 CORS,但浏览器会检查。它是保护一个站点调用其他站点的API。
所以您的解决方案是在 Grafana 前面放置一个反向 nginx 代理。下面是 docker-compose.yml
相同的
version: '2.1'
services:
grafana:
image: grafana/grafana
nginx:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "3000:80"
下面的nginx配置会添加CORS,但是很开放会允许所有人访问
events {
worker_connections 1024;
}
http {
#
# Acts as a nginx HTTPS proxy server
# enabling CORS only to domains matched by regex
# /https?://.*\.mckinsey\.com(:[0-9]+)?)/
#
# Based on:
# * http://blog.themillhousegroup.com/2013/05/nginx-as-cors-enabled-https-proxy.html
# * http://enable-cors.org/server_nginx.html
#
server {
listen 80;
location / {
#if ($http_origin ~* (https?://.*\.tarunlalwani\.com(:[0-9]+)?$)) {
# set $cors "1";
#}
set $cors "1";
# OPTIONS indicates a CORS pre-flight request
if ($request_method = 'OPTIONS') {
set $cors "${cors}o";
}
# Append CORS headers to any request from
# allowed CORS domain, except OPTIONS
if ($cors = "1") {
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Credentials true always;
proxy_pass http://grafana:3000;
}
# OPTIONS (pre-flight) request from allowed
# CORS domain. return response directly
if ($cors = "1o") {
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Headers' 'Origin,Content-Type,Accept' always;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
# Requests from non-allowed CORS domains
proxy_pass http://grafana:3000;
}
}
}
同样为了测试你不应该使用
xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
删除它并测试它应该工作
我在 Docker 容器中设置了 Grafana(来自 Docker 存储库的 grafana/grafana
图像),端口 3000 转发到我的本地主机。我的 docker-compose.yml
下面:
version: '2.1'
services:
grafana:
image: grafana/grafana
ports:
- 3000:3000
最初我也有 link 到 Graphite 和一些卷和环境配置(仅 GF_SECURITY_ADMIN_PASSWORD
),但我想这无关紧要。
我可以通过简单的 curl
调用从 Grafana 获得响应:
$ curl http://localhost:3000
<a href="/login">Found</a>.
但是当我试图通过 AJAX 调用获取它时,它给了我一个奇怪的结果:
$.ajax({url: 'http://localhost:3000', beforeSend: function(xhr, settings) {alert('before setting header'); xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); alert('after setting header');}});
[many JSON fields]
responseText:""
[many JSON fields]
statusText: "error"
[many JSON fields]
警报显示 header 已设置为接受来自任何来源的请求。
当我直接调用 Docker 容器地址时,也会发生同样的情况(curl 有效但 ajax 无效)。
后台发生了什么?为什么第二个请求不起作用?如何通过 AJAX 调用从 Grafana 获得响应?
问题是默认情况下 CORS 在 grafana 上未启用。 curl 请求不会检查 CORS,但浏览器会检查。它是保护一个站点调用其他站点的API。
所以您的解决方案是在 Grafana 前面放置一个反向 nginx 代理。下面是 docker-compose.yml
相同的
version: '2.1'
services:
grafana:
image: grafana/grafana
nginx:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "3000:80"
下面的nginx配置会添加CORS,但是很开放会允许所有人访问
events {
worker_connections 1024;
}
http {
#
# Acts as a nginx HTTPS proxy server
# enabling CORS only to domains matched by regex
# /https?://.*\.mckinsey\.com(:[0-9]+)?)/
#
# Based on:
# * http://blog.themillhousegroup.com/2013/05/nginx-as-cors-enabled-https-proxy.html
# * http://enable-cors.org/server_nginx.html
#
server {
listen 80;
location / {
#if ($http_origin ~* (https?://.*\.tarunlalwani\.com(:[0-9]+)?$)) {
# set $cors "1";
#}
set $cors "1";
# OPTIONS indicates a CORS pre-flight request
if ($request_method = 'OPTIONS') {
set $cors "${cors}o";
}
# Append CORS headers to any request from
# allowed CORS domain, except OPTIONS
if ($cors = "1") {
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Credentials true always;
proxy_pass http://grafana:3000;
}
# OPTIONS (pre-flight) request from allowed
# CORS domain. return response directly
if ($cors = "1o") {
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Headers' 'Origin,Content-Type,Accept' always;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
# Requests from non-allowed CORS domains
proxy_pass http://grafana:3000;
}
}
}
同样为了测试你不应该使用
xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
删除它并测试它应该工作