控制器內部對請求的操作

控制器內部對請求的操作
一Action方法
1調用方式
控制器處理請求時會找到與之名字匹配的action.
調用method_missing(),如果找不到action
調用模版,如果找不到action和method_missing()
調用錯誤報告Unknown Action如果上述都不符合
2禁止調用
將action聲明爲protected或private,也可以不改變私有性聲明爲hidden_action :XXX
3控制器環境
action_name 當前處理的action名稱
cookies與請求相關的cookie,相應時對象設置的值將保存到客戶機上
headers一個類似於hash的對象,代表HTTP頭信息,這些信息用於應答
params一個類似於hash的對象,存放着請求參數
request進入控制器的請求對象,包含屬性:
domain 返回請求地址中域名部分的最後兩段
remote_ip一字符串形式返回客戶端IP,若有代理則包含多個IP地址
env返回客戶瀏覽器設置的環境變量值如:request.env[‘XXX’]
method返回客戶端所使用的請求方法:delete,put,get,post….
delete?,get?,head?,post?,put?返回是否爲該方法:true or false
xml_http_request?和xhr?,請求來自AJAX則返回true 與method值無關
response代表HTTP應答的對象,在處理時rails填充這個對象
session一個類似與hash的對象,代表當前的session數據
4應答
模版的渲染(render:)
Rails內建支持3中模版:.rhtml格式內嵌ruby代碼的HTML代碼;構造器XML內容的方式;rjs,用於生成JavaScript
通過定義ActionController::Base.template_root=dir_path改變視圖根路徑,默認的視圖根路徑爲:app/views
render(:text=>string)將指定字符串發送給客戶端
render(:inline=>string,:type=>”rhtml”/”rxml”/”rjs”,:locals=>hash)把string內容作爲指定的type模版進行渲染,:locals提供局部模版中的變量
render(:action=>action_name,:locals=>hash)渲染控制器中指定的action對應的模版
render(:file=>path,:use_full_path=>true/false,:locals=>hash)渲染指定路徑的模版, 若設置:use_full_path=>true,則變爲相對路徑的方式尋找
render(:template=>name)  template必須同事包含控制器名和action名
render(:partial=>name)  渲染一個局部模版
render(:js=>”alert(‘xxx’)”) 將返回text/javascript格式
render(:nothing=>true)  什麼都不返回---返回一片空白給瀏覽器
render(:xml=>stuff)  以xml格式渲染,stuff將被強制轉換爲xml格式
render(:json=>stuff)  以json格式渲染,stuff將被強制轉換爲json格式
render(:update) do |page| …end以rjs模版渲染 從略
文件下載(send_data,send_file)
send_data(data, options)發送一個二進制數據流給客戶端
send_file(path, options)發送一個文件內容給客戶端
重定向(redirect_to)
Redirect_to(:action, options)options可以提供params的值
Redirect_to(:back)返回前一個action
5 cookie和session
cookie
cookie的創建:cookie的值必須是字符串
Cookies[:name]={:value=>值,:domain=>”http://www.xxx.com”,:path=>”/store”,: expires =>””,:secure=>”secure”/”空串” }
domain屬性用來設置所定義的Cookie變量的域,設置不同變量的域可以防止不同網站之間的Cookie相互衝突
path屬性用來設置所定義的Cookie變量的文件路徑,請求爲此路徑時cookie纔有效
expires屬性來設置它的生命期限。
secure屬性爲secure或爲空,WEB服務器之間就通過HTTPS或者其它安全協議傳遞數據
session
與cookie不同session是保存在服務器端的。建立會話後應用會爲session分配一個session_id,他將保存在cookie中以便用戶對session的訪問以及修改
Session中可以保存任意可以被序列化的對象。存儲ActiveRecord對象需在控制器中加入聲明——model : session的鍵,在聲明的控制器引用session便可爲模型對象進行序列化和反序列化的操作
1)Session自定義屬性:可在config/environment中設置config.action_controller.session.option的hash
:session_domain 用於保存session_id的cookie作用域,默認爲當前應用域名
:session_id如果不設置此項,新建session會自動得到一個32字長的id
:session_key用於保存session id的cookie名稱
:session_path有效的路徑範圍。默認值是/,既整個域名內有效
:session_secure如果設爲true,則只有當用http://開頭的地址訪問時session生效
2)Session的存儲
在config/environment中設置config.active_record.session_store的值來指定存儲機制,這個值由CGI::Session模塊中定義,除PStore與默認的cookiestore,其他存儲策略直接符號引用
session_store=CGI::Session:PStore方式
數據保存到PStore格式的文件中,2.x後被遺棄的方式
session_store=:active_record_store
數據保存到數據庫,通過rake db:sessions:create建立session表遷移任務。2.x後開啓此模式若同時需要csrf保護,需要設置csrf密鑰
session_store=:drb_store
數據保存到非web應用之外的服務器(而通過服務器這些數據又可以存儲到不同的物理位置,google採用了這種水平伸縮的吞吐)
其他存儲方式是不推薦作爲B/S架構的存儲方式。
3)session的過期
人工session過期可以使用reset_session(),是一種主動清除的策略;如果採用非cookiestore可以服務器刪除過期session的策略
Flash
Flash有session類似的功能,區別在於flash所記憶的內容只能提供給跳轉後的下一個action,所以我經常把flash又叫做小session
Flash的兩個方法:
flash.now[:key]=value此flash將能通過跳轉傳到下個action
成功跳轉後在跳轉後的action定義:flash.keep[:key]=value將保持傳遞性,將再傳遞到下一個action,從而實現了2次跳轉仍然保持原數據。
6過濾器與校驗
1)前置、後置、環繞過濾
before_filter:     前置
after_filter:  後置
around_filter: 環繞
注:一個controller中有多個前置、後置過濾器時,加入一個前置或後置過濾都將會添加到所有以添加的過濾器後,既先執行其他過濾後在執行 新加入的前置或後置過濾。若希望新加入的先被執行則前置:prepend_before_filter,後置:prepend_after_filter
環繞過濾與上述不同,當controller中有多個環繞過濾時,新加入的環繞則嵌套在其他環繞過濾中,就如同大家見過的嵌套循環的結構一樣
2)過濾形式
過濾方法:定義一個過濾方法通過xxx_filter: method引用,注:環繞過濾內部要用yield引入要執行的action
過濾模塊:  xxx_filter do |some_params|
some_params爲控制器參數
end
注:環繞過濾還要傳入另一個參數,該參數的call方法將執行過濾的action
過濾類:定義一個類,並創建類方法filter(some_params),過濾聲明爲xxx_filter 類,
當過濾器被調用,則類的filter方法被調用,並傳入控制器參數。注:環繞過濾需要在filter類方法中定義yield
3)過濾的有效範圍
xxx_filter:some_method,:only=>[:one_action,:two_action]指定需要過濾的action
xxx_filter:some_method,:except=>[:one_action,:two_action]指定不需要過濾的action
4)rails提供的內置過濾校驗
例:
verify :only=> :some_action  #需要過濾驗證的內容
:session=>:some_key  #判斷會話中有some_key的鍵值
:add_flash=>{:note=>”some_noties”} #上個條件不成立flash添加此信息
:redirect=>:some_action #條件不成立跳轉的action
有效範圍 :only=> :some_action 需要過濾的action
:except=> :some_action 不需要過濾的action
檢查條件 :flash=>:key  #flash中是否包含指定的鍵
:method=>:symbol  #請求方法(get、post、put等)
:params=>:key  #請求參數中包含指定的鍵
:session=>:key  #session中是否包含指定的鍵
:xhr=>true or false  #請求是否來自AJAX
動作 :add_flash=>hash  #將指定的hash放入flash
:add_headers=>hash  #應答頭信息放入hash的內容
:redirect_to=>url_for,params  #根據條件跳轉
:render=>params  #根據條件渲染模版
7緩存處理
三種緩存機制:
頁面緩存:將整個渲染後的頁面放入緩存,後續調用直接調用緩存
Action緩存:需經過filter後將action放入緩存,後續訪問通過過濾後若有此
緩存,則直接調用緩存
片段緩存:後面介紹
1)緩存鉤子(控制器中)
caches_page :some_action  #設定某個action的頁面緩存
caches_action :some_action  #設定某個action的action緩存
注:緩存只要在生產模式被開啓,手動設置爲在environement.rb中設置
config.action_controller.perform_caching=true,這裏特別要注意,不是所有內容都能緩存,對於可變性很大的內容最好不要緩存,這個需要根據開發經驗而定
2)手工清除緩存
緩存的內容被更新後,對於用戶緩存的內容沒有任何意義,並且沒用的緩存會佔用大量的資源。
expire_page :some_action  #清除指定action的頁面緩存
expire_action :some_action  #清除指定action的頁面緩存
3)緩存清掃器
人工清理緩存對於大型項目勢必要漏清,這裏引入清理器,清掃器應該放在model下
class SomeModelSweeper < ActionController::Caching::Sweeper
observe Article  #設置要監視的模型
#表中添加新數據後執行頁面緩存清理
def after_create(article)
expire_public_page
end
#表中數據被更新後執行action緩存清理
def after_update(article)
expire_article_page(article.id)
end
#表中數據被刪除一條或多條時同事執行頁面、action緩存清理
def after_destroy(article)
expire_public_page
expire_article_page(article.id)
end
private
def expire_public_page
expire_page(:controller => "content" , :action => 'public_content' )
end
def expire_article_page(article_id)
expire_action(:controller => "content" ,
:action => "premium_content" ,
:id => article_id)
end
end
控制器中的清理器鉤子(在控制器中)
cache_sweeper :article_sweeper,   #開啓Article清理器
:onlye=>:some_action  #監視的控制器
:except=>:some_action  #忽略的控制器
注:若要對可變性較大內容進行緩存需要引入時間緩存失效策略:通過操作系統編寫定時刪除緩存的進程來控制
8CSRF安全策略
Rails2.x後引入了防止跨域訪問攻擊的pluging,具體操作如下
在控制器中定義protect_from_forgery鉤子,在模版中使用form_for等標籤時,服務器會在生成form_for等標籤時 建立一個密鑰(token),服務器會監視request回來的所有post以及AJAX行爲,如果request沒有token或者與服務器計算出的不 一致,將返回錯誤信息。
cookiestore的session存儲機制下,token是根據CGI::Session.generate_unique_id生成的隨即數並進行編碼得到的,所以不需要爲protect_from_forgery設置secret的鍵值
:active_record_store是根據session_id、protect_from_forgery的secret的值以及digest(默認是SHA1)計算得來,所以要爲這種session機制設置secret值。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章