2016-05-17 14 views
0

我很努力地理解Ajax的概念。我的目標很簡單,就是提供一個自動完成表單的教育機構列表。目標:用戶輸入類似「University大學」,然後「滑鐵盧大學」的類型可能會出現。這裏是我的嵌入的Ruby是什麼樣子:Ajax Call ERror Cross Origin REquest:拉出大學自動填充列表的列表

<%= f.text_field :university, :id => "university-field", :onkeydown=>"updateUniSearch()" %> 

而且我的javascript:

 function updateUniSearch() { 
     /*jQuery UI Autocomplete for University Search Form*/ 
     $("#university-field").autocomplete({ 
      dataType: "json", 
      source: "http://universities.hipolabs.com", 
     async: true, 
      crossdomain: true 
     }); 
    }; 

我找到一所大學的名稱列表API在這裏:https://github.com/Hipo/university-domains-list

目前,當我跑我的網頁,我得到出現以下錯誤:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://universities.hipolabs.com/?term=university. (Reason: CORS header 'Access-Control-Allow-Origin' missing). 

我是否正確地做到這一點,或者我走了嗎?同樣,我只是想使用自動完成來顯示來自外部源的大學列表,而不是試圖找到大量的大學列表,並將它們保存在本地數組或JavaScript中的某些內容中。先謝謝你。

回答

1

出於安全原因,數據類型json不支持跨源請求。改爲使用jsonp(帶填充的JSON)。

0

瀏覽器不允許跨域Ajax請求,除非CSP (Content Sharing Policy)允許該域或數據源提供Cross-Origin Resource Sharing (CORS)標頭。

class ApplicationController 

    before_action :set_csp, if: { request.format.html? } 

    private 
    def set_csp 
     response.headers['Content-Security-Policy'] = "connect-src http://universities.hipolabs.com 'self'" 
    end 
end 

然而,CSP和CORS是一個相對較新的創新 - 在天回做AJAX是通過利用在Same Origin Policy孔,該孔允許從任何域中加載腳本的唯一途徑。

這個用途就是所謂的JSONP--你把JSON放在一個javascript函數中。爲了使其工作,您調用的API必須提供JSONP響應。

不幸http://universities.hipolabs.com/search不提供JSONP響應。

您可以通過爲DOM添加腳本標記來加載數據 - 當它完成加載時,它會調用包裝JSON的回調函數。聽起來很愚蠢?是的。幸運的是,您今天很少需要使用JSONP,因爲大多數有價值的API都會發送CORS頭文件,並且CSP得到了廣泛的支持。

因此,您需要僅僅依靠CSP或通過您自己的服務器代理請求。

require 'net/http' 
class UniversitiesController < ApplicationController 
    def search 
    uri = URI("http://universities.hipolabs.com") 
    uri.query = URI.encode_www_form(params.permit(:name, :country)) 
    res = Net::HTTP.get_response(uri) 
    if res.is_a?(Net::HTTPSuccess) 
     render json: res.body 
    else 
     head res.code.to_i 
    end 
    end 
end 

或者只是找到一個更好的數據源,使用CORS來允許跨域訪問。