SlideShare a Scribd company logo
1 of 152
Download to read offline
Rails と Rack と HTTP と通信の話
なんとなく動いた、から一歩踏み込むエンジニアリング
2019/11/22
自己紹介
• 菅宮佑介 / Yusuke Sugamiya / @DNPP
• Progate でプログラマーやってます。
• Ruby と bash スクリプトを使ってサーバーサイド方面の仕事をやってる
ことが多いです。
• 前職では iOS アプリを書いてました。Swift は最高。
Web サービス作ってますか?
Web アプリケーション
フレームワーク使ってますか?
Web Application Framework?
Web Application Framework?
Rails?
Web Application Framework?
Rails?
Sinatra?
Web Application Framework?
Rails?
Sinatra?
Django?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Laravel?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Laravel?
express?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Laravel?
express?
gin?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Laravel?
express?
gin?
Perfect?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Laravel?
express?
gin?
Perfect?
Kitura?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Laravel?
express?
gin?
Perfect?
Kitura?
Vapor?
Web Application Framework?
Rails?
Sinatra?
Django?
CakePHP?
Symfony?
Laravel?
express?
gin?
Perfect?
Kitura?
Vapor?
Spring?
😇😇
そもそも Web サービスとは?
Web アプリケーションとは?
A. ユーザーに何かのサービスを
提供するアプリケーション。
サービスとは…?
🤔🤔
サービスを提供するコンピュータがいる。
サービスを提供するコンピュータがいる。
(大体サーバーと呼ばれます)
サービスを提供するコンピュータがいる。
(大体サーバーと呼ばれます)
↓
サービスを提供するコンピュータがいる。
(大体サーバーと呼ばれます)
↓
サービスを受けるコンピュータがいる。
サービスを提供するコンピュータがいる。
(大体サーバーと呼ばれます)
↓
サービスを受けるコンピュータがいる。
(大体クライアントと呼ばれます)
サービスを提供するコンピュータがいる。
(大体サーバーと呼ばれます)
↓
サービスを受けるコンピュータがいる。
(大体クライアントと呼ばれます)
↓
サービスを提供するコンピュータがいる。
(大体サーバーと呼ばれます)
↓
サービスを受けるコンピュータがいる。
(大体クライアントと呼ばれます)
↓
サービスは情報のやり取りという形で実現される。
サービスを提供するコンピュータがいる。
(大体サーバーと呼ばれます)
↓
サービスを受けるコンピュータがいる。
(大体クライアントと呼ばれます)
↓
サービスは情報のやり取りという形で実現される。
(最終的に人間が情報を解釈することによって価値が生まれます)
情報のやりとり?
通信だ!
通信の話をします。
通信とは
情報を伝達する手段のこと
情報を伝達する手段のこと
• 会話
情報を伝達する手段のこと
• 会話
• 手紙
情報を伝達する手段のこと
• 会話
• 手紙
• 狼煙
狼煙はすごい
徒歩に比べて圧倒的なスピードで遠くに情報を伝えられる。
しかし欠点もあり、伝達できる情報量がとても少ない。
なんとか工夫して狼煙の利点を上手い
具合に享受したくないですか?
事前にいくつかの取り決めを
しておけば良さそうですね。
現代のインターネットにも
同じことが言えます。
様々な物理現象をうまく利用して、
それに人間が意味合いを持たせて、
なんとか便利に使っています。
OSI 参照モデル・TCP/IP モデル
https://japan.zdnet.com/keyword/OSI参照モデル/
OSI 参照モデル・TCP/IP モデル
https://japan.zdnet.com/keyword/OSI参照モデル/
HTTP の話
なんで HTTP の話になるの?
普通の Web アプリケーションは、
情報を大体全部 HTTP の上に
乗せて通信しているからです。
HTTP を理解することが Web アプリ
ケーションを理解する一つの道です。
もちろん他にも沢山の道があります。
HTTP とは
HTTP とは
Hypertext Transfer Protocol
HTTP とは
Hypertext Transfer Protocol
• Hypertext → 要するに人間が読める文字。テキスト。
• Hypertext → 要するに人間が読める文字。テキスト。
• Transfer → 運ぶ。送る。移転する。そういう感じ。
• Hypertext → 要するに人間が読める文字。テキスト。
• Transfer → 運ぶ。送る。移転する。そういう感じ。
• Protocol → 規約とか規格とか約束事とかそういう概念。
Hypertext
なんと「人間が読める」という非常に便利な特性があります。
cURL コマンドによる実例
$ curl http://example.com
$ curl http://example.com
<!doctype html>
<html>
<head>
<title>Example Domain</title>
[ ... 中略 ... ]
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
😄😄 HTML 😄😄
😄😄 HTML 😄😄
Hypertext Markup Language
😆😆 HTML 😆😆
Hypertext Markup Language
ばっちり読めますね。
事前にいくつかの取り決めをしているとのことだったけど、
その決まり事は誰が決めているの?
RFC
RFC とは
Request for Comments
インターネットで用いられるさまざまな技術の標準化や運用に関する事項な
ど幅広い情報共有を行うために公開される文書シリーズです。
https://www.nic.ad.jp/ja/newsletter/No24/090.html
RFC とは
Request for Comments
RFCは、1968年ごろ、スティーブ・クロッカー が考案したと言われており、
はじめのRFCは1969年4月7日の日付となっている
https://ja.wikipedia.org/wiki/Request_for_Comments
👴👴 1969年 👵👵
HTTP/0.9
1991年
HTTP/1.0
1996年5月
RFC 1945 : https://tools.ietf.org/html/rfc1945
HTTP/1.1
1997年1月
RFC 2068 : https://tools.ietf.org/html/rfc2068
RFC 2616 : https://tools.ietf.org/html/rfc2616
HTTP/2 もあります。
2015年2月くらいの話ですが、
この場では割愛します。
🤔🤔Web 業界は変化が早い?🤔🤔
HTTP は少なくとも 20 年以上、
そして今後も使われ続ける
技術の基礎と言えます。
技術の根幹を構成しているもの
を知ることは大事ですね?
RFC には本質の全てがあります。
RFC には本質の全てがあります。
本当かな…
HTTP の仕様の話
リクエストとレスポンス
ヘッダとボディ
•リクエストヘッダ
•リクエストボディ
•レスポンスヘッダ
•レスポンスボディ
$ curl --verbose http://example.com
$ curl --verbose http://example.com
* Trying 93.184.216.34...
* TCP_NODELAY set
* Connected to example.com (93.184.216.34) port 80 (#0)
$ curl --verbose http://example.com
* Trying 93.184.216.34...
* TCP_NODELAY set
* Connected to example.com (93.184.216.34) port 80 (#0)
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.64.1
> Accept: */*
>
リクエストヘッダ
空行
$ curl --verbose http://example.com
[...]
< HTTP/1.1 200 OK
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 21 Nov 2019 10:07:23 GMT
< Etag: "3147526947+gzip+ident"
< Expires: Thu, 28 Nov 2019 10:07:23 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECS (sjc/4E68)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
<
レスポンスヘッダ
空行
$ curl --verbose http://example.com
<!doctype html>
<html>
<head>
<title>Example Domain</title>
[...]
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
レスポンスボディ
$ curl --verbose http://example.com
<!doctype html>
<html>
<head>
<title>Example Domain</title>
[...]
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
* Connection #0 to host example.com left intact
* Closing connection 0
完全に理解した。
完全に理解した。
本当かな…
メソッドの話。
GET
POST
PUT
DELETE
HEAD
OPTIONS
(他にもあるよ)
$ curl --verbose http://example.com
* Trying 93.184.216.34...
* TCP_NODELAY set
* Connected to example.com (93.184.216.34) port 80 (#0)
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.64.1
> Accept: */*
>
リクエストヘッダ
$ curl --verbose http://example.com
* Trying 93.184.216.34...
* TCP_NODELAY set
* Connected to example.com (93.184.216.34) port 80 (#0)
> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.64.1
> Accept: */*
>
これ
一般的に、クライアントから指定されたメソッドによって
サーバーの挙動を適切に変える、ということをします。
POST が飛んできたら、クライアントはこういうことを望んでいるだろう、
サーバーはこういう挙動をするだろう、といった共通認識があることと思います。
ステータスコードの話
• 100番台 → 役に立ちそうな情報を返すよ。(実際に使うことはほぼ無い)
• 100番台 → 役に立ちそうな情報を返すよ。(実際に使うことはほぼ無い)
• 200番台 → 成功したよ。
• 100番台 → 役に立ちそうな情報を返すよ。(実際に使うことはほぼ無い)
• 200番台 → 成功したよ。
• 300番台 → どこかに移動したよ。移動先を参照してね。
• 100番台 → 役に立ちそうな情報を返すよ。(実際に使うことはほぼ無い)
• 200番台 → 成功したよ。
• 300番台 → どこかに移動したよ。移動先を参照してね。
• 400番台 → クライアント(そっち側)にエラーがあるよ。直してね。
• 100番台 → 役に立ちそうな情報を返すよ。(実際に使うことはほぼ無い)
• 200番台 → 成功したよ。
• 300番台 → どこかに移動したよ。移動先を参照してね。
• 400番台 → クライアント(そっち側)にエラーがあるよ。直してね。
• 500番台 → サーバー(こっち側)にエラーがあるよ。ごめんね。
$ curl --verbose http://example.com
[...]
< HTTP/1.1 200 OK
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 21 Nov 2019 10:07:23 GMT
< Etag: "3147526947+gzip+ident"
< Expires: Thu, 28 Nov 2019 10:07:23 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECS (sjc/4E68)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
<
レスポンスヘッダ
空行
$ curl --verbose http://example.com
[...]
< HTTP/1.1 200 OK
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 21 Nov 2019 10:07:23 GMT
< Etag: "3147526947+gzip+ident"
< Expires: Thu, 28 Nov 2019 10:07:23 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECS (sjc/4E68)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
<
$ curl --verbose http://example.com
[...]
< HTTP/1.1 200 OK
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 21 Nov 2019 10:07:23 GMT
< Etag: "3147526947+gzip+ident"
< Expires: Thu, 28 Nov 2019 10:07:23 GMT
< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
< Server: ECS (sjc/4E68)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1256
<
成功したよ
理解しやすい。
頻出ステータスコードは覚えよう。
頻出のヘッダも覚えよう。
頻出のヘッダはやってればなんとなくわかる。
RFC にも色々定義されているものがあるので
そちらを見ましょう。
ステートレスという大事な特性の話。
毎度 HTTP の通信の度に、
「前回の通信した内容」や「通信相手」を
覚えてなくても大丈夫だよ。
通信相手を識別する方法は HTTP の規格側で
は面倒を見ないけど、やりたかったら各アプリ
ケーションで好きにやってね、ということ。
Rack の話
https://github.com/rack/rack
Rack が抽象化しているものは
HTTP のリクエストとレスポンス
run Proc.new do |env|
[
200,
{'Content-Type' => 'text/plain'},
['Hello']
]
end
Rack の最小の使い方
run Proc.new do |env|
[
200,
{'Content-Type' => 'text/plain'},
['Hello']
]
end
env にはクライアントからの
リクエストの情報が入ってるよ。
レスポンスのステータスコード
レスポンスヘッダ
レスポンスボディ
Rack のエンドポイントとして次の Proc を使うよ。
なるほどですね。
もうちょっと良い感じにします。
class Hello
def call(env)
[200, {'Content-Type' => 'text/plain'}, ["Hello Rackn"]]
end
end
run Hello.new
class Hello
def call(env)
[200, {'Content-Type' => 'text/plain'}, ["Hello Rackn"]]
end
end
run Hello.new
$ curl http://localhost:9292/
class Hello
def call(env)
[200, {'Content-Type' => 'text/plain'}, ["Hello Rackn"]]
end
end
run Hello.new
$ curl http://localhost:9292/
Hello Rack
いい感じですね。
middleware を挟んでみましょう。
class Secret
def initialize(app)
@app = app
end
def call(env)
if env["PATH_INFO"] == '/secret'
[200, {'Content-Type' => 'text/plain'}, ["This is Secretn"]]
else
@app.call(env)
end
end
end
class Hello
def call(env)
[200, {'Content-Type' => 'text/plain'}, ["Hello Rackn"]]
end
end
run Secret.new(Hello.new)
class Secret
def initialize(app)
@app = app
end
def call(env)
if env["PATH_INFO"] == '/secret'
[200, {'Content-Type' => 'text/plain'}, ["This is Secretn"]]
else
@app.call(env)
end
end
end
class Hello
def call(env)
[200, {'Content-Type' => 'text/plain'}, ["Hello Rackn"]]
end
end
run Secret.new(Hello.new)
middleware として使う class を Rack の
インターフェースに従った形で作るよ。
/secret にアクセスしたときだけ This is Secret と
返して、それ以外のときは処理を他に丸投げするよ。
Secret をエンドポイントにして、丸投げ先を Hello にするよ。
$ curl http://localhost:9292/
Hello Rack
$ curl http://localhost:9292/hello
$ curl http://localhost:9292/
Hello Rack
$ curl http://localhost:9292/hello
Hello Rack
$ curl http://localhost:9292/
Hello Rack
$ curl http://localhost:9292/secret
$ curl http://localhost:9292/hello
Hello Rack
$ curl http://localhost:9292/
Hello Rack
$ curl http://localhost:9292/secret
This is Secret
$ curl http://localhost:9292/hello
Hello Rack
$ curl http://localhost:9292/
Hello Rack
🎉🎉
ちょっとイヤな予感がする部分
run Secret.new(Hello.new)
run Function.new(Secret.new(Hello.new(Hi.new)))
ちょっとイヤな予感がする部分
middleware が増えたら大体こうなっていきそう…。
use Function
use Secret
use Hello
run Hi.new
こういう風に縦に並べて書けます。
🎉🎉
https://github.com/rack/rack
https://github.com/rack/rack
改めて
なんで Rack の話をしたの?
Rails も Rack に乗っかってるからです。
$ ./bin/rails middleware
$ ./bin/rails middleware
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Sprockets::Rails::QuietAssets
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use WebConsole::Middleware
use ActionDispatch::DebugExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
run MyApp::Application.routes
…こんなに沢山必要なの?
これは人類の英知の結晶です。
ありがたく使いましょう。
そしてきちんと内部まで調べましょう。
まとめ
まとめ
• Web 業界は変化が早いといった話は正しい部分もあるけど、どの業界だって変化が早い部分と
基礎になっていて、そうそう変わらない部分はあるよ。
まとめ
• Web 業界は変化が早いといった話は正しい部分もあるけど、どの業界だって変化が早い部分と
基礎になっていて、そうそう変わらない部分はあるよ。
• 変化しない部分はどこにあるのかということを知っていると生きやすくなるよ。この業界におい
て、それは主に「標準化された規格」と「コンピュータサイエンス」の部分に集中してるよ。
まとめ
• Web 業界は変化が早いといった話は正しい部分もあるけど、どの業界だって変化が早い部分と
基礎になっていて、そうそう変わらない部分はあるよ。
• 変化しない部分はどこにあるのかということを知っていると生きやすくなるよ。この業界におい
て、それは主に「標準化された規格」と「コンピュータサイエンス」の部分に集中してるよ。
• 先人の知恵は偉大だよ。巨人の肩には素直に乗るのがいいよ。自分で作ると大体事故るよ。とは
いえ先人がどういった工夫をして、今何故そうなっているのかを地道に調べることは大事だよ。
まとめ
• Web 業界は変化が早いといった話は正しい部分もあるけど、どの業界だって変化が早い部分と
基礎になっていて、そうそう変わらない部分はあるよ。
• 変化しない部分はどこにあるのかということを知っていると生きやすくなるよ。この業界におい
て、それは主に「標準化された規格」と「コンピュータサイエンス」の部分に集中してるよ。
• 先人の知恵は偉大だよ。巨人の肩には素直に乗るのがいいよ。自分で作ると大体事故るよ。とは
いえ先人がどういった工夫をして、今何故そうなっているのかを地道に調べることは大事だよ。
• シンプルとイージーは違うよ。この暗黙知が多く求められる Web 業界では初学者にとってシン
プルなものは少ないよ。(故に高度な技能職であるとされている側面もあると思うよ。)
終

More Related Content

Similar to Rails と Rack と HTTP と通信の話

Beginning Java EE 6 勉強会(7) #bje_study
Beginning Java EE 6 勉強会(7) #bje_studyBeginning Java EE 6 勉強会(7) #bje_study
Beginning Java EE 6 勉強会(7) #bje_study
ikeyat
 
Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成
krdlab
 
about Thrift
about Thriftabout Thrift
about Thrift
Naoya Ito
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
Shinpei Ohtani
 

Similar to Rails と Rack と HTTP と通信の話 (20)

Let's make your CDN with RUBY
Let's make your CDN with RUBYLet's make your CDN with RUBY
Let's make your CDN with RUBY
 
web server
web serverweb server
web server
 
Ruby on Rails Tutorial Chapter5-7
Ruby on Rails Tutorial Chapter5-7Ruby on Rails Tutorial Chapter5-7
Ruby on Rails Tutorial Chapter5-7
 
Apacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasiaApacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasia
 
第9回rest勉強会 ダウンロード・アップロード編
第9回rest勉強会 ダウンロード・アップロード編第9回rest勉強会 ダウンロード・アップロード編
第9回rest勉強会 ダウンロード・アップロード編
 
Beginning Java EE 6 勉強会(7) #bje_study
Beginning Java EE 6 勉強会(7) #bje_studyBeginning Java EE 6 勉強会(7) #bje_study
Beginning Java EE 6 勉強会(7) #bje_study
 
Thrift
ThriftThrift
Thrift
 
Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成
 
Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
 
AWSとmod_pagespeedで 楽々サクサク高速化!!
AWSとmod_pagespeedで楽々サクサク高速化!!AWSとmod_pagespeedで楽々サクサク高速化!!
AWSとmod_pagespeedで 楽々サクサク高速化!!
 
about Thrift
about Thriftabout Thrift
about Thrift
 
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみようAlfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
 
HTML5 on ASP.NET
HTML5 on ASP.NETHTML5 on ASP.NET
HTML5 on ASP.NET
 
WebSocket Chat App Hands On on Microsoft Azure
WebSocket Chat App Hands On on Microsoft AzureWebSocket Chat App Hands On on Microsoft Azure
WebSocket Chat App Hands On on Microsoft Azure
 
いよいよ始められる Java EEでのWebSocket #jjug #jjug_ccc #ccc_r21
いよいよ始められる Java EEでのWebSocket #jjug #jjug_ccc #ccc_r21いよいよ始められる Java EEでのWebSocket #jjug #jjug_ccc #ccc_r21
いよいよ始められる Java EEでのWebSocket #jjug #jjug_ccc #ccc_r21
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
Rancher2.3とwindows Containerで作るkubernetesクラスタ
Rancher2.3とwindows Containerで作るkubernetesクラスタRancher2.3とwindows Containerで作るkubernetesクラスタ
Rancher2.3とwindows Containerで作るkubernetesクラスタ
 
PSGIへの誘い
PSGIへの誘いPSGIへの誘い
PSGIへの誘い
 
SocketStream入門
SocketStream入門SocketStream入門
SocketStream入門
 

Rails と Rack と HTTP と通信の話