2017-01-12 31 views
1

我想從Rails public/目錄提供一個生成的靜態網站(包含文檔)。我的目錄結構是這樣的:Rails:不允許訪問靜態資產目錄沒有結尾/

`-- rails-root 
    | [...] 
    |-- public 
    | |-- assets 
    | | |-- favicon.png 
    | | |-- fonts 
    | | | `-- ... 
    | | |-- images 
    | | | `-- ... 
    | | |-- javascripts 
    | | | `-- ... 
    | | `-- stylesheets 
    | |  `-- ... 
    | |-- documentation 
    | | |-- GLOSSARY.html 
    | | |-- index.html 
    | | `-- ... 

我複製我生成的文件rails-root/public/documentation,一切都很好,只要我要求它http://<site>/documentation/http://<site>/documentation/index.html

但是,當我要求http://<site>/documentation導軌試圖有幫助,並提供我的index.html頁面。頁面中的所有鏈接都是相對的,所以從不同的基礎(根目錄)而不是目錄(documentation/)提供的鏈接使其無法加載任何資產,看起來不合適,並且無法從所有鏈接導航。

我試圖建立一個路由進行重定向,以防有人請求http://<site>/documentation(不帶後綴斜線):

get '/documentation', :to => redirect('/documentation/index.html') 

這是不行的,我猜是因爲public文件優先在路由?我也嘗試一個僞造的路徑只是爲了驗證我的路由代碼是正確的,它的工作:

get '/xxx', :to => redirect('/documentation/index.html') 

我想無論是防止鐵軌被幫助的(我很好用404 http://<site>/documentation只要尾隨/ works; 404比一個破損的頁面更好)或重定向。我正在使用Rails 4.2。任何想法歡迎!

回答

1

ActionDispatch::Static中間件負責爲靜態內容提供服務,並且即使在沒有結尾斜槓的情況下訪問該目錄也會導致這種行爲。

似乎沒有一種很好的方法來改變這種行爲而沒有猴子修補或分叉這個中間件。

但是,如果你真行與開銷,解決方法是觀察請求路徑/ PATH_INFO的改變由ActionDispatch::Static並利用這些信息來寫截獲並重定向目錄,而斜線中間件:

module Rack 
    class RedirectStaticWithoutTrailingSlash 
    def initialize(app) 
     @app = app 
    end 

    def call(env) 
     request = Rack::Request.new(env) 
     original_path_info = request.path_info 

     response = @app.call(env) 

     updated_path_info = request.path_info 

     if serving_index_for_path_without_trailing_slash?(original_path_info, updated_path_info) 
     redirect_using_trailing_slash(original_path_info) 
     else 
     response 
     end 
    end 

    def serving_index_for_path_without_trailing_slash?(original_path_info, updated_path_info) 
     updated_path_info.end_with?('index.html') && 
     original_path_info != updated_path_info && 
     !original_path_info.end_with?('/') 
    end 

    def redirect_using_trailing_slash(path) 
     redirect("#{path}/") 
    end 

    def redirect(url) 
     [301, {'Location' => url, 'Content-Type' => 'text/html'}, ['Moved Permanently']] 
    end 
    end 
end 

這個中間件將需要配置在軌配置ActionDispatch之前採取行動:

config.middleware.insert_before('ActionDispatch::Static', 'Rack::RedirectStaticWithoutTrailingSlash') 

這種方法的缺點是,你還在做R的所有工作讀取文件並準備請求,並且由於它沒有使用任何類型的文檔行爲,它可能會在未來的rails版本中崩潰。