Upload
takashi-sakaguchi
View
1.126
Download
8
Embed Size (px)
DESCRIPTION
tottoruby
Citation preview
Rack 触ってみたRack 触ってみた本当に触ってみただけ
@hamajyotan
アジェンダ3本立て
近況報告
Rack ことはじめ, 触ってみる (Main)
触って困ったところ少し
雑談, 質疑応答
01 34
いまここ3本立て
近況報告 <== いまここ
Rack ことはじめ, 触ってみる
触って困ったところ少し
雑談, 質疑応答
02 34
近況報告まゆしぃ
トゥットゥルー, まだ数話しかみてない
野球で西武がビリでびっくりした
野球には全く興味がない
自分が知っている西武は常勝チームだった
室伏さんマジかっこいい
室伏になら投げられてもいい
03 34
いまここ3本立て
近況報告
Rack ことはじめ, 触ってみる <== いまここ
触って困ったところ少し
雑談, 質疑応答
04 34
ことはじめ, 触ってみるRack って何?
ちょっとググればわかることを得意げに話します
概要とか
仕組みとか
触ってみる
触ってみます
05 34
Rack とはWeb サーバと Web アプリの架け橋, グルー, I/F
色んな Web サーバ
webrick, thin, mongrel, passenger, unicorn, ..
色んな Web アプリ (framework)
rails, sinatra, camping, ...
Web サーバとアプリケーションの間のお約束
06 34
どんなお約束なの ?#call ってメッセージに反応するなにか
1つの引数を受け付ける
リクエストを意味する Hash
3つの要素を持つ Array を返す
ステータスコード
レスポンスヘッダを意味する Hash
レスポンスボディを意味する Array
07 34
つまりこんな感じ
Proc.new { |env| [ 200, {'Content-Type' => 'text/html'}, ['Hello, World!'] ]}
08 34
config.ru
require 'rubygems'require 'rack'
app = Proc.new { |env| [ 200, {'Content-Type' => 'text/html'}, ['Hello, World!'] ]}run app09 34
実行してみる
$ rackup [2011-08-30 11:18:31] INFO WEBrick 1.3.1[2011-08-30 11:18:31] INFO ruby 1.9.2 (2011-02-18) [i686-linux][2011-08-30 11:18:31] INFO WEBrick::HTTPServer#start: pid=8494 port=9292
10 34
リクエストしてみる
$ telnet 127.0.0.1 9292Trying 127.0.0.1...Connected to 127.0.0.1.Escape character is '^]'.GET / HTTP/1.1
HTTP/1.1 200 OK Content-Type: text/plainTransfer-Encoding: chunkedServer: WEBrick/1.3.1 (Ruby/1.9.2/2011-02-18)Date: Tue, 30 Aug 2011 02:09:49 GMTContent-Length: 23Connection: Keep-Alive
dHello, World!0
Connection closed by foreign host.11 34
反応してる
$ rackup [2011-08-30 11:18:31] INFO WEBrick 1.3.1[2011-08-30 11:18:31] INFO ruby 1.9.2 (2011-02-18) [i686-linux][2011-08-30 11:18:31] INFO WEBrick::HTTPServer#start: pid=8494 port=9292127.0.0.1 - - [30/Aug/2011 11:18:40] "GET / HTTP/1.1" 200 - 0.0012
12 34
mongrel で動かすには ?
$ rackup -s mongrel
13 34
passenger では ?config.ru 以外に少し必要
public/ ディレクトリ (空っぽでOK)
(任意) tmp/restart.txt
apache を再起動せずにアプリを再起動できる
14 34
pasenger で動かす-1
$ tree /home/hamajyotan/rack/test
/home/hamajyotan/rack/test├── config.ru├── public└── tmp └── restart.txt
15 34
passenger で動かす-2/home/hamajyotan/rack/test/ に配置されている前提で・・
<VirtualHost *:80> RackEnv production ServerName www.yourhost.com DocumentRoot /home/hamajyotan/rack/test/public <Directory /home/hamajyotan/rack/test/public> AllowOverride all Options -MultiViews </Directory></VirtualHost>
16 34
env って何が入っているの?
# config.rurequire 'rack'require 'yaml'run Proc.new { |env| [ 200, {'Content-Type' => 'text/plain', [env.to_yaml], ]}
17 34
env の中身
--- GATEWAY_INTERFACE: CGI/1.1PATH_INFO: /QUERY_STRING: ""REMOTE_ADDR: 127.0.0.1REMOTE_HOST: localhostREQUEST_METHOD: GETREQUEST_URI: http://localhost:9292/SCRIPT_NAME: ""SERVER_NAME: localhostSERVER_PORT: "9292"SERVER_PROTOCOL: HTTP/1.1SERVER_SOFTWARE: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)HTTP_HOST: localhost:9292HTTP_CONNECTION: keep-aliveHTTP_USER_AGENT: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.218 Safari/535.1HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8HTTP_ACCEPT_ENCODING: gzip,deflate,sdchHTTP_ACCEPT_LANGUAGE: ja,en-US;q=0.8,en;q=0.6HTTP_ACCEPT_CHARSET: Shift_JIS,utf-8;q=0.7,*;q=0.3rack.version: - 1- 1rack.input: !ruby/object:Rack::Lint::InputWrapper input: !ruby/object:StringIO {}
rack.errors: !ruby/object:Rack::Lint::ErrorWrapper error: !ruby/object:IO {}
rack.multithread: truerack.multiprocess: falserack.run_once: falserack.url_scheme: httpHTTP_VERSION: HTTP/1.1REQUEST_PATH: /
18 34
ここまでのまとめrack 仕様に準拠したコード
#call - リクエストを引数に、レスポンスを返す関数
config.ru ってファイルを準備
#call に反応するインスタンスを run に与える
rack の仕様に準拠したサーバならどこでも動く
webrick, mongrel, passenger, ...
env の中にはリクエストに関する情報がある
path とか port とか useragent とか
method とか body とか19 34
Rack ミドルウェア基本は一緒
#call ってメッセージに応答
{ before | after } フィルタ
他の Rack アプリを内包する
デザパタで言うところの Decorator パターン
20 34
コードでおk?
class Middleware def initialize app @app = app end
def call env # before... code, header, body = @app.call env # after... [code, header, body] endend21 34
処理後レスポンスヘッダ付加
class AddServerHeader def initialize app @app = app end
def call env code, header, body = @app.call env header['Server'] = "#{header['Server']} (*^o^)=3" [code, header, body] endend
22 34
どうやって使う ?
# config.rurequire 'rack'require 'add_server_header'
app = Proc.new { |env| [200, {'Content-Type' => 'text/plain'}, ['Hello, World']]}
use AddServerHeaderrun app
23 34
use がキモ
# これはuse AddServerHeaderrun app
# これと同じmiddleware = AddServerHeader.new(app)run middleware
24 34
use がキモ
# これはuse AddServerHeaderuse Otherrun app
# これと同じmiddleware = AddServerHeader.new(Other.new(app))run middleware
25 34
use がキモ
# これはuse AddServerHeaderuse AddServerHeaderrun app
# これと同じmiddleware = AddServerHeader.new(AddServerHeader.new(app))run middleware
26 34
いろんなミドルウェアRack::Auth::Basic
基本認証を実現
Rack::Static
静的ファイルを出力する
Rack::ConditionalGet
条件付き GET を実現
Etc..
27 34
例えば基本認証
# config.rurequire 'rack'app = Proc.new { |env| [200, {'Content-Type' => 'text/plain'}, ['Hello, World']]}use Rack::Auth::Basic, 'mayusi-' do |user, pass| user == 'mayusi-' && pass == 'mayusi-!'endrun app
# ちなみ use 以下はこれと同じ# auth = Rack::Auth::Basic.new(app, 'mayusi-') do |user, pass|# user == 'mayusi-' && pass == 'mayusi-!'# end# run auth
28 34
ここまでのまとめミドルウェア
基本は rack アプリケーションと同じ
#call を持つ
env を引数に受け取る
レスポンスを返す
他のアプリケーションを Decorator パターンで内包する
29 34
いまここ3本立て
近況報告
Rack ことはじめ, 触ってみる
触って困ったところ少し <== いまここ
雑談, 質疑応答
30 34
困ったところWEBrick
'Content-Length: 0' をガン無視
env['CONTENT_LENGTH'] = '0' って設定してくれない
他の Web サーバはしてくれた
GET パラメータのセパレータ
& だけでなく、 ; もセパレータ扱い
RFC 的に正しいか良く分かっていません
31 34
Paranoia なところHTTP のヘッダ名
大文字小文字区別しても良いのか否か?
アンダースコアをヘッダ名にできないけど・・
x-hoge-hogehoge: fuga# => env['HTTP_X_HOGE_HOGEHOGE'] = 'fuga'x-hoge_HogeHoge: piyo# => env['HTTP_X_HOGE_HOGEHOGE'] = 'piyo'
32 34
最後にrack を利用したアプリケーション例
というか宣伝 ?
https://github.com/hamajyotan/castoro-s3-adapter
castoro-s3-adapter ってのを作成中です
castoro をバックエンドにした Amazon s3 実装
というか castoro を S3 プロトコルでアクセス可能にするもの
33 34
おわりですご清聴有難うございます
質問ありましたらどうぞ
雑談でもおk
34 34