-
Notifications
You must be signed in to change notification settings - Fork 0
/
rails_on_rack.html
579 lines (539 loc) · 29.9 KB
/
rails_on_rack.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rails on Rack — Ruby on Rails 指南</title>
<meta name="description" content="Ruby on Rails 指南:系統學習 Rails(Rails 4.2 版本)" >
<meta name="keywords" content="Ruby on Rails Guides 指南 中文 學習 免費 網路 Web 開發" >
<meta name="author" content="http://git.io/G_R1sA">
<meta property="fb:admins" content="1340181291">
<meta property="og:title" content="Rails on Rack — Ruby on Rails 指南" >
<meta property="og:site_name" content="Ruby on Rails 指南">
<meta property="og:image" content="http://rails.ruby.tw/images/rails_guides_cover.jpg">
<meta property="og:url" content="http://rails.ruby.tw/">
<meta property="og:type" content="article">
<meta property="og:description" content="Ruby on Rails 指南:系統學習 Rails(Rails 4.2 版本)">
<link rel="stylesheet" href="stylesheets/application.css">
<link href="http://fonts.googleapis.com/css?family=Noto+Sans:400,700|Noto+Serif:700|Source+Code+Pro" rel="stylesheet">
<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon">
</head>
<body class="guide">
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/zh-TW/sdk.js#xfbml=1&appId=837401439623727&version=v2.0";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<script type="text/javascript">
window.twttr=(function(d,s,id){var t,js,fjs=d.getElementsByTagName(s)[0];if(d.getElementById(id)){return}js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);return window.twttr||(t={_e:[],ready:function(f){t._e.push(f)}})}(document,"script","twitter-wjs"));
</script>
<div id="topNav">
<div class="wrapper">
<strong class="more-info-label">更多內容 <a href="http://rubyonrails.org/">rubyonrails.org:</a></strong>
<span class="red-button more-info-button">
更多內容
</span>
<ul class="more-info-links s-hidden">
<li class="more-info"><a href="http://rubyonrails.org/">綜覽</a></li>
<li class="more-info"><a href="http://rubyonrails.org/download">下載</a></li>
<li class="more-info"><a href="http://rubyonrails.org/deploy">部署</a></li>
<li class="more-info"><a href="https://github.com/rails/rails">原始碼</a></li>
<li class="more-info"><a href="http://rubyonrails.org/screencasts">影片</a></li>
<li class="more-info"><a href="http://rubyonrails.org/documentation">文件</a></li>
<li class="more-info"><a href="http://rubyonrails.org/community">社群</a></li>
<li class="more-info"><a href="http://weblog.rubyonrails.org/">Blog</a></li>
</ul>
</div>
</div>
<div id="header">
<div class="wrapper clearfix">
<h1><a href="index.html" title="回首頁">Guides.rubyonrails.org</a></h1>
<ul class="nav">
<li><a class="nav-item" href="index.html">首頁</a></li>
<li class="guides-index guides-index-large">
<a href="index.html" id="guidesMenu" class="guides-index-item nav-item">指南目錄</a>
<div id="guides" class="clearfix" style="display: none;">
<hr>
<dl class="L">
<dt>起步走</dt>
<dd><a href="getting_started.html">Rails 起步走</a></dd>
<dt>Models</dt>
<dd><a href="active_record_basics.html">Active Record 基礎</a></dd>
<dd><a href="active_record_migrations.html">Active Record 遷移</a></dd>
<dd><a href="active_record_validations.html">Active Record 驗證</a></dd>
<dd><a href="active_record_callbacks.html">Active Record 回呼</a></dd>
<dd><a href="association_basics.html">Active Record 關聯</a></dd>
<dd><a href="active_record_querying.html">Active Record 查詢</a></dd>
<dt>Views</dt>
<dd><a href="layouts_and_rendering.html">Rails 算繪與版型</a></dd>
<dd><a href="form_helpers.html">Action View 表單輔助方法</a></dd>
<dt>Controllers</dt>
<dd><a href="action_controller_overview.html">Action Controller 綜覽</a></dd>
<dd><a href="routing.html">Rails 路由:深入淺出</a></dd>
</dl>
<dl class="R">
<dt>深入了解</dt>
<dd><a href="active_support_core_extensions.html">Active Support 核心擴展</a></dd>
<dd><a href="i18n.html">Rails 國際化 API</a></dd>
<dd><a href="action_mailer_basics.html">Action Mailer 基礎</a></dd>
<dd><a href="active_job_basics.html">Active Job 基礎</a></dd>
<dd><a href="security.html">Rails 安全指南</a></dd>
<dd><a href="debugging_rails_applications.html">除錯 Rails 應用程式</a></dd>
<dd><a href="configuring.html">Rails 應用程式設定</a></dd>
<dd><a href="command_line.html">Rake 任務與 Rails 命令列工具</a></dd>
<dd><a href="asset_pipeline.html">Asset Pipeline</a></dd>
<dd><a href="working_with_javascript_in_rails.html">在 Rails 使用 JavaScript</a></dd>
<dd><a href="constant_autoloading_and_reloading.html">Constant Autoloading and Reloading</a></dd>
<dt>擴充 Rails</dt>
<dd><a href="rails_on_rack.html">Rails on Rack</a></dd>
<dd><a href="generators.html">客製與新建 Rails 產生器</a></dd>
<dd><a href="rails_application_templates.html">Rails 應用程式模版</a></dd>
<dt>貢獻 Ruby on Rails</dt>
<dd><a href="contributing_to_ruby_on_rails.html">貢獻 Ruby on Rails</a></dd>
<dd><a href="api_documentation_guidelines.html">API 文件準則</a></dd>
<dd><a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南準則</a></dd>
<dt>維護方針</dt>
<dd><a href="maintenance_policy.html">維護方針</a></dd>
<dt>發佈記</dt>
<dd><a href="upgrading_ruby_on_rails.html">升級 Ruby on Rails</a></dd>
<dd><a href="4_2_release_notes.html">Ruby on Rails 4.2 發佈記</a></dd>
<dd><a href="4_1_release_notes.html">Ruby on Rails 4.1 發佈記</a></dd>
<dd><a href="4_0_release_notes.html">Ruby on Rails 4.0 發佈記</a></dd>
<dd><a href="3_2_release_notes.html">Ruby on Rails 3.2 發佈記</a></dd>
<dd><a href="3_1_release_notes.html">Ruby on Rails 3.1 發佈記</a></dd>
<dd><a href="3_0_release_notes.html">Ruby on Rails 3.0 發佈記</a></dd>
<dd><a href="2_3_release_notes.html">Ruby on Rails 2.3 發佈記</a></dd>
<dd><a href="2_2_release_notes.html">Ruby on Rails 2.2 發佈記</a></dd>
<dt>Rails 指南翻譯術語</dt>
<dd><a href="translation_terms.html">翻譯術語</a></dd>
</dl>
</div>
</li>
<li><a class="nav-item" href="//github.com/docrails-tw/guides">貢獻翻譯</a></li>
<li><a class="nav-item" href="contributing_to_ruby_on_rails.html">貢獻</a></li>
<li><a class="nav-item" href="credits.html">致謝</a></li>
<li class="guides-index guides-index-small">
<select class="guides-index-item nav-item">
<option value="index.html">指南目錄</option>
<optgroup label="起步走">
<option value="getting_started.html">Rails 起步走</option>
</optgroup>
<optgroup label="Models">
<option value="active_record_basics.html">Active Record 基礎</option>
<option value="active_record_migrations.html">Active Record 遷移</option>
<option value="active_record_validations.html">Active Record 驗證</option>
<option value="active_record_callbacks.html">Active Record 回呼</option>
<option value="association_basics.html">Active Record 關聯</option>
<option value="active_record_querying.html">Active Record 查詢</option>
</optgroup>
<optgroup label="Views">
<option value="layouts_and_rendering.html">Rails 算繪與版型</option>
<option value="form_helpers.html">Action View 表單輔助方法</option>
</optgroup>
<optgroup label="Controllers">
<option value="action_controller_overview.html">Action Controller 綜覽</option>
<option value="routing.html">Rails 路由:深入淺出</option>
</optgroup>
<optgroup label="深入了解">
<option value="active_support_core_extensions.html">Active Support 核心擴展</option>
<option value="i18n.html">Rails 國際化 API</option>
<option value="action_mailer_basics.html">Action Mailer 基礎</option>
<option value="active_job_basics.html">Active Job 基礎</option>
<option value="security.html">Rails 安全指南</option>
<option value="debugging_rails_applications.html">除錯 Rails 應用程式</option>
<option value="configuring.html">Rails 應用程式設定</option>
<option value="command_line.html">Rake 任務與 Rails 命令列工具</option>
<option value="asset_pipeline.html">Asset Pipeline</option>
<option value="working_with_javascript_in_rails.html">在 Rails 使用 JavaScript</option>
<option value="constant_autoloading_and_reloading.html">Constant Autoloading and Reloading</option>
</optgroup>
<optgroup label="擴充 Rails">
<option value="rails_on_rack.html">Rails on Rack</option>
<option value="generators.html">客製與新建 Rails 產生器</option>
<option value="rails_application_templates.html">Rails 應用程式模版</option>
</optgroup>
<optgroup label="貢獻 Ruby on Rails">
<option value="contributing_to_ruby_on_rails.html">貢獻 Ruby on Rails</option>
<option value="api_documentation_guidelines.html">API 文件準則</option>
<option value="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南準則</option>
</optgroup>
<optgroup label="維護方針">
<option value="maintenance_policy.html">維護方針</option>
</optgroup>
<optgroup label="發佈記">
<option value="upgrading_ruby_on_rails.html">升級 Ruby on Rails</option>
<option value="4_2_release_notes.html">Ruby on Rails 4.2 發佈記</option>
<option value="4_1_release_notes.html">Ruby on Rails 4.1 發佈記</option>
<option value="4_0_release_notes.html">Ruby on Rails 4.0 發佈記</option>
<option value="3_2_release_notes.html">Ruby on Rails 3.2 發佈記</option>
<option value="3_1_release_notes.html">Ruby on Rails 3.1 發佈記</option>
<option value="3_0_release_notes.html">Ruby on Rails 3.0 發佈記</option>
<option value="2_3_release_notes.html">Ruby on Rails 2.3 發佈記</option>
<option value="2_2_release_notes.html">Ruby on Rails 2.2 發佈記</option>
</optgroup>
<optgroup label="Rails 指南翻譯術語">
<option value="translation_terms.html">翻譯術語</option>
</optgroup>
</select>
</li>
</ul>
</div>
</div>
</div>
<hr class="hide">
<div id="feature">
<div class="wrapper">
<h2>Rails on Rack</h2><p>本篇介紹 Rails 與 Rack 的整合、如何與其他 Rack 組件互動。</p><p>讀完本篇,您將了解:</p>
<ul>
<li>如何在 Rails 裡使用 Rack Middleware。</li>
<li>ActionPack Middleware 的內部工作原理。</li>
<li>如何自定 Middleware。</li>
</ul>
<div id="subCol">
<h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
<ol class="chapters">
<li><a href="#rack-%E7%B0%A1%E4%BB%8B">Rack 簡介</a></li>
<li>
<a href="#rails-on-rack">Rails on Rack</a>
<ul>
<li><a href="#rails-%E6%87%89%E7%94%A8%E7%A8%8B%E5%BC%8F%E7%9A%84-rack-%E7%89%A9%E4%BB%B6">Rails 應用程式的 Rack 物件</a></li>
<li><a href="#rails-server"><code>rails server</code></a></li>
<li><a href="#rackup"><code>rackup</code></a></li>
<li><a href="#%E9%96%8B%E7%99%BC%E8%87%AA%E5%8B%95%E9%87%8D%E8%BC%89">開發自動重載</a></li>
</ul>
</li>
<li>
<a href="#action-dispatcher-middleware-stack">Action Dispatcher Middleware Stack</a>
<ul>
<li><a href="#%E6%AA%A2%E8%A6%96-middleware-stack">檢視 Middleware Stack</a></li>
<li><a href="#%E8%A8%AD%E5%AE%9A-middleware-stack">設定 Middleware Stack</a></li>
<li><a href="#%E5%85%A7%E9%83%A8-middleware-stack">內部 Middleware Stack</a></li>
</ul>
</li>
<li>
<a href="#%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99">參考資料</a>
<ul>
<li><a href="#%E5%AD%B8%E7%BF%92-rack">學習 Rack</a></li>
<li><a href="#%E7%90%86%E8%A7%A3-middlewares">理解 Middlewares</a></li>
</ul>
</li>
</ol>
</div>
</div>
</div>
<div id="container">
<div class="wrapper">
<div id="mainCol">
<div class="warning"><p>本篇需要先了解 Rack 協定,以及 Rack 的相關概念,譬如:什麼是 Middleware、什麼是 URL 映射以及 <code>Rack::Builder</code> 等知識。</p></div><h3 id="rack-簡介">1 Rack 簡介</h3><p>Rack 給使用 Ruby 開發的網路應用程式,提供了精簡、模組化、容易介接的介面。Rack 將 HTTP 請求與響應,盡可能包裝成最簡單的形式,給網路框架、伺服器以及框架與伺服器之間的軟體(Middleware)提供了一個統一的 API 接口,<code>call</code> 方法。</p><p>更多內容請參考:<a href="http://rack.github.io/">Rack API 文件</a>。</p><p>深入解釋 Rack 超出本篇的範疇。若不熟悉 Rack 的基礎知識,請閱讀<a href="#%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99">參考資料</a>一節。</p><h3 id="rails-on-rack">2 Rails on Rack</h3><h4 id="rails-應用程式的-rack-物件">2.1 Rails 應用程式的 Rack 物件</h4><p><code>ApplicationName::Application</code> 是 Rails 應用程式主要的 Rack 物件。任何與 Rack 相容的 Web 伺服器,都應該使用 <code>ApplicationName::Application</code> 物件來執行 Rails 應用程式。<code>Rails.application</code> 是 <code>ApplicationName::Application</code> 物件 的引用。</p><h4 id="rails-server">2.2 <code>rails server</code>
</h4><p><code>rails server</code> 建立 <code>Rack::Server</code> 物件並啟動伺服器。</p><p>以下是 <code>rails server</code> 如何建立 <code>Rack::Server</code> 的實體。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
Rails::Server.new.tap do |server|
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
end
</pre>
</div>
<p><code>Rails::Server</code> 繼承自 <code>Rack::Server</code>,並呼叫 <code>Rack::Server#start</code> 方法:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class Server < ::Rack::Server
def start
...
super
end
end
</pre>
</div>
<p>以下是如何載入 Middlewares:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
def middleware
middlewares = []
middlewares << [Rails::Rack::Debugger] if options[:debugger]
middlewares << [::Rack::ContentLength]
Hash.new(middlewares)
end
</pre>
</div>
<p><code>Rails::Rack::Debugger</code> 主要只在開發模式下有用。下表解釋了加載的 Middleware 的用途:</p>
<table>
<thead>
<tr>
<th style="text-align: left">Middleware</th>
<th style="text-align: left">用途</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left">Rails::Rack::Debugger</td>
<td style="text-align: left">啟動 Debugger</td>
</tr>
<tr>
<td style="text-align: left">Rack::ContentLength</td>
<td style="text-align: left">計算響應有幾個 byte,並設定 HTTP Content-Length 標頭</td>
</tr>
</tbody>
</table>
<h4 id="rackup">2.3 <code>rackup</code>
</h4><p>若想用 <code>rackup</code> 來取代 <code>rails server</code>,可以修改 Rails 應用程式根目錄下的 <code>config.ru</code>:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# Rails.root/config.ru
require ::File.expand_path('../config/environment', __FILE__)
use Rack::Debugger
use Rack::ContentLength
run Rails.application
</pre>
</div>
<p>啟動伺服器:</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rackup config.ru
</pre>
</div>
<p>了解 <code>rackup</code> 接受的其他選項:</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rackup --help
</pre>
</div>
<h4 id="開發自動重載">2.4 開發自動重載</h4><p>Middlewares 只會載入一次,察覺不到新的修改。有關 Middleware 的修改需要重新啟動伺服器才行。</p><h3 id="action-dispatcher-middleware-stack">3 Action Dispatcher Middleware Stack</h3><p>許多 Action Dispatcher 的內部組件都是以 Rack Middleware 的方式所實作。<code>Rails::Application</code> 使用了 <code>ActionDispatch::MiddlewareStack</code>,將內部與外部的 Middleware 結合起來,形成完整的 Rails Rack 應用程式。</p><div class="note"><p>Rails 的 <code>ActionDispatch::MiddlewareStack</code> 等同於 <code>Rack::Builder</code>,但靈活性更高、更多功能,專門為了滿足 Rails 需求所打造。</p></div><h4 id="檢視-middleware-stack">3.1 檢視 Middleware Stack</h4><p>Rails 有一個好用的 Rake 任務,可檢視使用中的 Middleware stack:</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ bin/rake middleware
</pre>
</div>
<p>新建出來的 Rails 應用程式,輸出結果會像是:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000029a0838>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run Rails.application.routes
</pre>
</div>
<p>上列 Middlewares 在<a href="#%E5%85%A7%E9%83%A8-middleware-stack">內部 Middlewares</a> 一節分別介紹。</p><h4 id="設定-middleware-stack">3.2 設定 Middleware Stack</h4><p>Rails 提供了簡單的設定接口:<code>config.middleware</code>,用來新增、刪除、修改 Middleware Stack 裡的 Middleware。可以在 <code>application.rb</code> 或是特定環境的設定檔:<code>environments/<environment>.rb</code> 來使用這個設定。</p><h5 id="新增-middleware">3.2.1 新增 Middleware</h5><p>使用下面任一方法來新增 Middleware 到 Middleware Stack:</p><p><strong><code>config.middleware.use(new_middleware, args)</code></strong></p>
<ul>
<li>新增 Middleware 到 Middleware Stack 的底部</li>
</ul>
<p><strong><code>config.middleware.insert_before(existing_middleware, new_middleware, args)</code></strong></p>
<ul>
<li>新增 Middleware 在某個現有的 Middleware 之前。</li>
</ul>
<p><strong><code>config.middleware.insert_after(existing_middleware, new_middleware, args)</code></strong></p>
<ul>
<li>新增 Middleware 在某個現有的 Middleware 之後。</li>
</ul>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# config/application.rb
# Push Rack::BounceFavicon at the bottom
config.middleware.use Rack::BounceFavicon
# Add Lifo::Cache after ActiveRecord::QueryCache.
# Pass { page_cache: false } argument to Lifo::Cache.
config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, page_cache: false
</pre>
</div>
<h5 id="交換-middleware-順序">3.2.2 交換 Middleware 順序</h5><p>使用 <code>config.middleware.swap</code> 來交換現有 Middleware Stack 中,Middleware 的順序。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# config/application.rb
# Replace ActionDispatch::ShowExceptions with Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
</pre>
</div>
<h5 id="刪除-middleware">3.2.3 刪除 Middleware</h5><p>加入下行程式碼到應用程式設定檔,來刪除 Middleware:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# config/application.rb
config.middleware.delete "Rack::Lock"
</pre>
</div>
<p>現在檢視 Middleware Stack,會發現 <code>Rack::Lock</code> 已經被刪除了。</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ bin/rake middleware
use Rack::Sendfile
use ActionDispatch::Static
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000029a0838>
use Rack::Runtime
...
run Rails.application.routes
</pre>
</div>
<p>若想移除與 Session 有關的 Middleware:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# config/application.rb
config.middleware.delete "ActionDispatch::Cookies"
config.middleware.delete "ActionDispatch::Session::CookieStore"
config.middleware.delete "ActionDispatch::Flash"
</pre>
</div>
<p>或移除與瀏覽器相關的 Middleware:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# config/application.rb
config.middleware.delete "Rack::MethodOverride"
</pre>
</div>
<h4 id="內部-middleware-stack">3.3 內部 Middleware Stack</h4><p>Action Controller 大多數的功能皆以 Middleware 的方式實作,以下解釋每個 Middleware 的用途:</p><p><strong><code>Rack::Sendfile</code></strong></p>
<ul>
<li>設定伺服器的 <code>X-Sendfile</code> 標頭(header)。使用 <code>config.action_dispatch.x_sendfile_header</code> 來設定。</li>
</ul>
<p><strong><code>ActionDispatch::Static</code></strong></p>
<ul>
<li>用來決定是否由 Rails 提供靜態 assets。使用 <code>config.serve_static_assets</code> 選項來啟用或禁用(<code>true</code> 啟用)。</li>
</ul>
<p><strong><code>Rack::Lock</code></strong></p>
<ul>
<li>將 <code>env["rack.multithread"]</code> 設為 <code>false</code> ,則可將應用程式包在 Mutex 裡。</li>
</ul>
<p><strong><code>ActiveSupport::Cache::Strategy::LocalCache::Middleware</code></strong></p>
<ul>
<li>用來做 memory cache。注意,此 cache 不是線程安全的。</li>
</ul>
<p><strong><code>Rack::Runtime</code></strong></p>
<ul>
<li>設定 X-Runtime 標頭,並記錄請求的執行時間(秒為單位)。</li>
</ul>
<p><strong><code>Rack::MethodOverride</code></strong></p>
<ul>
<li>如有設定 <code>params[:_method]</code>,則允許可以重寫方法。這個 Middleware 實作了 HTTP <code>PUT</code> 與 <code>DELETE</code> 方法。</li>
</ul>
<p><strong><code>ActionDispatch::RequestId</code></strong></p>
<ul>
<li>在響應中產生獨立的 <code>X-Request-Id</code> 標頭,並啟用 <code>ActionDispatch::Request#uuid</code> 方法。</li>
</ul>
<p><strong><code>Rails::Rack::Logger</code></strong></p>
<ul>
<li>請求開始時通知 Log,請求結束寫入 Log。</li>
</ul>
<p><strong><code>ActionDispatch::ShowExceptions</code></strong></p>
<ul>
<li>Rescue 任何由應用程式拋出的異常,並呼叫處理異常的程式,將異常以適合的格式顯示給使用者。</li>
</ul>
<p><strong><code>ActionDispatch::DebugExceptions</code></strong></p>
<ul>
<li>負責記錄異常,並在請求來自本機時,顯示除錯頁面。</li>
</ul>
<p><strong><code>ActionDispatch::RemoteIp</code></strong></p>
<ul>
<li>檢查 IP 欺騙攻擊。</li>
</ul>
<p><strong><code>ActionDispatch::Reloader</code></strong></p>
<ul>
<li>準備與清除回呼。主要在開發模式下用來重新加載程式碼。</li>
</ul>
<p><strong><code>ActionDispatch::Callbacks</code></strong></p>
<ul>
<li>處理請求前,先執行預備好的回呼。</li>
</ul>
<p><strong><code>ActiveRecord::Migration::CheckPending</code></strong></p>
<ul>
<li>檢查是否有未執行的遷移檔案,有的話拋出 <code>PendingMigrationError</code> 錯誤。</li>
</ul>
<p><strong><code>ActiveRecord::ConnectionAdapters::ConnectionManagement</code></strong></p>
<ul>
<li>每個請求結束後,若 <code>rack.test</code> 不為真,則將作用中的連線清除。</li>
</ul>
<p><strong><code>ActiveRecord::QueryCache</code></strong></p>
<ul>
<li>啟用 Active Record 的查詢快取。</li>
</ul>
<p><strong><code>ActionDispatch::Cookies</code></strong></p>
<ul>
<li>幫請求設定 Cookie。</li>
</ul>
<p><strong><code>ActionDispatch::Session::CookieStore</code></strong></p>
<ul>
<li>負責把 Session 存到 Cookie。</li>
</ul>
<p><strong><code>ActionDispatch::Flash</code></strong></p><p><code>config.action_controller.session_store</code> 設定為真時,設定<a href="action_controller_overview.html#%E6%8F%90%E7%A4%BA%E8%A8%8A%E6%81%AF">提示訊息</a>的鍵。</p><p><strong><code>ActionDispatch::ParamsParser</code></strong></p>
<ul>
<li>解析請求的參數放到 <code>params</code> Hash 裡。</li>
</ul>
<p><strong><code>ActionDispatch::Head</code></strong></p>
<ul>
<li>將 HTTP <code>HEAD</code> 請求轉換成 <code>GET</code> 請求處理。</li>
</ul>
<p><strong><code>Rack::ConditionalGet</code></strong></p>
<ul>
<li>給伺服器加入 HTTP 的 Conditional <code>GET</code> 支持,頁面沒有變化,就不會回傳響應。</li>
</ul>
<p><strong><code>Rack::ETag</code></strong></p>
<ul>
<li>為所有字串 Body 加上 ETag 標頭,用來驗證快取。</li>
</ul>
<div class="info"><p>以上所有的 Middleware 都可以在自定的 Rack Stack 使用。</p></div><h3 id="參考資料">4 參考資料</h3><h4 id="學習-rack">4.1 學習 Rack</h4>
<ul>
<li><a href="http://rack.github.io">Rack 官方網站</a></li>
<li><a href="http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html">介紹 Rack</a></li>
<li><a href="http://m.onkey.org/ruby-on-rack-1-hello-rack">Ruby on Rack #1 - Hello Rack!</a></li>
<li><a href="http://m.onkey.org/ruby-on-rack-2-the-builder">Ruby on Rack #2 - The Builder</a></li>
<li><a href="http://railscasts.com/episodes/317-rack-app-from-scratch">#317 Rack App from Scratch (pro) - RailsCasts</a></li>
<li><a href="http://railscasts.com/episodes/222-rack-in-rails-3">#222 Rack in Rails 3 - RailsCasts</a></li>
</ul>
<h4 id="理解-middlewares">4.2 理解 Middlewares</h4>
<ul>
<li><a href="https://github.com/rack/rack/wiki/List-of-Middleware">List of Rack Middlewares</a></li>
<li><a href="http://railscasts.com/episodes/151-rack-middleware">Railscast on Rack Middlewares</a></li>
</ul>
<h3>反饋</h3>
<p>
歡迎幫忙改善指南的品質。
</p>
<p>
如發現任何錯誤之處,歡迎修正。開始貢獻前,可以先閱讀<a href="http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#contributing-to-the-rails-documentation">貢獻指南:文件</a>。
</p>
<p>翻譯如有錯誤,深感抱歉,歡迎 <a href="https://github.com/docrails-tw/guides/fork">Fork</a> 修正,或至此處<a href="https://github.com/docsrails-tw/guides/issues/new">回報</a>。</p>
<p>
文章可能有未完成或過時的內容。請先檢查 <a href="http://edgeguides.rubyonrails.org">Edge Guides</a> 來確定問題在 master 是否已經修掉了。再上 master 補上缺少的文件。內容參考 <a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南準則</a>來了解行文風格。
</p>
<p>最後,任何關於 Ruby on Rails 文件的討論,歡迎至 <a href="http://groups.google.com/group/rubyonrails-docs">rubyonrails-docs 郵件論壇</a>。
</p>
</div>
</div>
</div>
<hr class="hide">
<div id="footer">
<div class="wrapper">
<p>本著作係採用<a href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh_TW">創用 CC 姓名標示-相同方式分享 4.0 國際授權條款</a>授權。</p>
<p>“Rails”、“Ruby on Rails”,以及 Rails logo 為 David Heinemeier Hansson 的商標。版權所有。</p>
</div>
</div>
<script src="javascripts/jquery.min.js"></script>
<script src="javascripts/responsive-tables.js"></script>
<script src="javascripts/guides.js"></script>
<script src="javascripts/syntaxhighlighter/shCore.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushRuby.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushXml.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushSql.js"></script>
<script src="javascripts/syntaxhighlighter/shBrushPlain.js"></script>
<script type="text/javascript">
SyntaxHighlighter.all();
$(guidesIndex.bind);
</script>
<script>
(function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,"script","//www.google-analytics.com/analytics.js","ga");
ga("create", "UA-49903900-1", "auto");
ga("require", "displayfeatures");
ga("send", "pageview");
</script>
</body>
</html>