问题描述
我正在React中构建一个Chrome扩展程序,该扩展程序已连接到后端的Rails 6应用程序。我希望Rails应用程序充当API并存储扩展中的数据,但是我无法让它接受扩展中的请求。
fetch('https://www.myapp.com/api/post_comment/test',{
method: 'get',headers: {'Content-Type':'application/json'}
});
这是我一直在我的js控制台中遇到的错误:
可从原始位置访问“ https://www.myapp.com/api/test” “ http:// localhost:3000”已被CORS政策阻止:对 预检请求未通过访问控制检查:否 请求中出现“ Access-Control-Allow-Origin”标头 资源。如果不透明的响应满足您的需求,请设置请求的 模式设置为“ no-cors”,以在禁用CORS的情况下获取资源。
“ https://www.myapp.com/api/test”的FetchEvent导致网络 错误响应:传递给非响应的对象 responseWith()。
我尝试将rack-cors gem添加到我的Rails应用程序中:
#Gemfile:
gem 'rack-cors'
#config/initializers/cors.rb:
Rails.application.config.middleware.insert_before 0,Rack::Cors do
allow do
origins '*'
resource '/api/*',headers: :any,methods: [:get,:post,:patch,:put]
end
end
before_action :cors_preflight_check
after_action :cors_set_access_control_headers
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST,PUT,DELETE,GET,OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin,X-Requested-With,Content-Type,Accept,Authorization'
end
# If this is a preflight OPTIONS request,then short-circuit the
# request,return only the necessary headers and return an empty
# text/plain.
def cors_preflight_check
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST,Authorization'
render :text => '',:content_type => 'text/plain'
end
如果我在提取代码中添加mode: 'no-cors',
,则可以发布数据,但无法检索数据。
解决方法
将配置从config/cors.rb
移至config/initializers/cors.rb
config/initializers/
中的所有文件都将在Rails启动时加载。
还可以通过Rails 6的新功能来阻止不需要的主机。
将以下代码段添加到config/application.rb
中的config/environments/
或env特定文件中
config.hosts.clear
检查Upgraded Rails to 6,getting Blocked host Error
,在扩展程序中,您有两个来源-内容脚本注入到的页面的来源和后台脚本的来源。
要使后台脚本能够连接到您的api-您需要在清单的"https://www.myapp.com/"
中添加permissions
,而无需定期进行CORS检查。内容脚本可以通过message passing与后台对话,因此可以避免CORS:
// from content script:
chrome.runtime.sendMessage({action: "doSomeAction"},function(response) {
console.log(response);
});
//in background script:
chrome.runtime.onMessage.addListener(
function(request,sender,sendResponse) {
console.log(sender.tab ? "from a content script:" + sender.tab.url : "from the extension");
if (request.action == "doSomeAction") {
fetch('https://www.myapp.com/api/post_comment/test',{
method: 'get',headers: {'Content-Type':'application/json'}
}).then(function(response){
// do something with response and pass pack to content script:
sendResponse({foo: "bar"});
});
return true; // keep message channel so sendResponse is available in
}
});
关于rails CORS-我首先要确保标题存在:
curl -IX OPTIONS https://www.myapp.com/api/post_comment/test -H 'Access-Control-Request-Method: GET' -H 'Origin: http://someorigin.example.com'
这应该返回以下内容:
HTTP/2 200
server: nginx
date: Thu,22 Oct 2020 19:50:00 GMT
access-control-allow-origin: http://someorigin.example.com
access-control-allow-methods: GET,POST,OPTIONS
access-control-expose-headers:
access-control-max-age: 7200
cache-control: no-cache
x-request-id: 5846b7400a15b19398c96bec7faac570
x-runtime: 0.001532