之前有提過
Rack 會傳遞 Request 給 HTTP
我們要來模擬 Rack 的 Request 以及 Response
還記得呼叫 Rack 所需要的三個要素嗎? 狀態、Header、Body
Rack 會從 myrequest = Request.new(env) 進行解析
# rainbow/lib/rainbow/controller.rb
require "rack/request"
module Rainbow
class Controller
def request
@request ||= Rack::Request.new(@env)
end
def params
request.params
end
end
end
設定 request 方法
如果有 @request ||= 就抓 @request,沒有就 new 一個出來
Rack::Request 已經幫我們解析好 params 物件了
所以直接取用就可以了
# best_quotes/app/controllers/quotes_controller.rb
class QuotesController < Rainbow::Controller
def show
quote = FileModel.find(params["id"])
render :quote, :obj => quote
end
end
把畫面切到 http://localhost:3001/quotes/show?id=1
就會看到 plain as day
# best_quotes/app/controllers/quotes_controller.rb
class QuotesController < Rainbow::Controller
def show
quote = FileModel.find(params["id"])
ua = request.user_agent
render :quote, :obj => quote, :ua => ua
end
end
我們還需要改一下 view
# best_quotes/app/views/quotes/quote.html.erb
<p>
"<%= obj["quote"] %>"
<br/> – <%= obj["attribution"] %>
</p>
<p>
Submitted by <%= obj["submitter"] %>
</p>
<p>
Viewing with user agent: <%= ua %>
</p>
回來看一下 http://localhost:3001/quotes/show?id=1
在底下你會看到
Mozilla/5.0
(Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Chrome/537.36
這串字是瀏覽器用來讓 web server 辨識的
會根據你使用的瀏覽器而有所不同
現在我們來做 response 吧
使用 Rack::Response 建立
打開 rainbow/lib/rainbow/controller.rb
# rainbow/lib/rainbow/controller.rb
module Rainbow
class Controller
def response(text, status = 200, headers = {})
raise "Already responded!" if @response
a = [text].flatten
@response = Rack::Response.new(a, status, headers)
end
def get_response
@response
end
def render_response(*args)
response(render(*args))
end
end
end
# rainbow/lib/rainbow.rb:
module Rainbow
class Application
def call(env) # Redefine
if env['PATH_INFO'] == '/favicon.ico'
return [404, {'Content-Type' => 'text/html'}, []]
end
klass, act = get_controller_and_action(env)
controller = klass.new(env)
text = controller.send(act)
r = controller.get_response
if r
[r.status, r.headers, [r.body].flatten]
else
[200, {'Content-Type' => 'text/html'}, [text]]
end
end
end
end
打開 quotes_controller
# best_quotes/app/controllers/quotes_controller.rb
class QuotesController
def show
quote = FileModel.find(params["id"])
ua = request.user_agent
render_response :quote, :obj => quote, :ua => ua
end
end