рд░реИрдХ рдореЗрдВ рддреНрд╡рд░рд┐рдд рдкреНрд░рд╡реЗрд╢

рд░реИрдХ рдХреНрдпрд╛ рд╣реИ?


рд░реИрдХ рдордгрд┐ рдХреЗ рд▓реЗрдЦрдХ рдХреНрд░рд┐рд╢реНрдЪрд┐рдпрди рдиреНрдпреВрдХрд┐рд░реНрдЪреЗрди рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдпрд╣ рд░реВрдмреА (WEBrick, Mongrel, рдЖрджрд┐) рдФрд░ рд░реВрдмреА рд╡реЗрдм рдлреНрд░реЗрдорд╡рд░реНрдХ (рд░реЗрд▓, рд╕рд┐рдирд╛рддреНрд░рд╛, рдЖрджрд┐) рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╡реЗрдм рд╕рд░реНрд╡рд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдиреНрдпреВрдирддрдо рдПрдкреАрдЖрдИ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдлреНрд░реЗрдорд╡рд░реНрдХ рдЬреИрд╕реЗ рд╕рд┐рдирд╛рддреНрд░рд╛ рдХреЛ рд░реИрдХ рдХреЗ рдКрдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдпрд╛ рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХ рд░реИрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реИ рдЬреЛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рд░реНрд╡рд░ рдХреЛ рдЙрдирд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рд░реИрдХ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рд╕рд░рд▓ рд╣реИ - рдпрд╣ HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИред

HTTP рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╣реИ: рдпрд╣ рдореВрд▓ рд░реВрдк рд╕реЗ рдЙрд╕ рдбреЗрдЯрд╛ рдХреЗ рдкреНрд░рд╛рд░реВрдк рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╕рд░реНрд╡рд░ рдХреЛ рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЬрд┐рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред HTTP рдЕрдиреБрд░реЛрдз рдФрд░ HTTP рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдПрдХ рд╕рдорд╛рди рд╕рдВрд░рдЪрдирд╛ рд╣реИред рдПрдХ HTTP рдЕрдиреБрд░реЛрдз рдПрдХ рдЯреНрд░рд┐рдкрд▓-рдореЗрдердб-рд░рд┐рд╕реЛрд░реНрд╕ рдЬреЛрдбрд╝реА, рд╣реЗрдбрд░ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдФрд░ рдПрдХ рдЕрдиреБрд░реЛрдз рдирд┐рдХрд╛рдп рд╣реИ, рдЬрдмрдХрд┐ рдПрдХ HTTP HTTP рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛрдб, рд╣реЗрдбрд░ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдФрд░ рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдмреЙрдбреА рд╣реЛрддреА рд╣реИред

рдореИрдкрд┐рдВрдЧ рд░реИрдХ рдЗрд╕рдХреЗ рдХрд░реАрдм рд╣реИред рд░реИрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рд░реВрдмреА рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдХреЙрд▓ рд╡рд┐рдзрд┐ рд╣реЛрддреА рд╣реИ рдЬреЛ рдПрдХрд▓ рддрд░реНрдХ - рдкрд░реНрдпрд╛рд╡рд░рдг рд▓реЗрддреА рд╣реИ, рдФрд░ рддреАрди рддрддреНрд╡реЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд▓реМрдЯрд╛рддреА рд╣реИ: рд╕реНрдерд┐рддрд┐, рд╣реЗрдбрд░ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдмреЙрдбреАред

рд░реИрдХ рдореЗрдВ рд╣реИрдВрдбрд▓рд░ рдФрд░ рдПрдбреЗрдкреНрдЯрд░ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдкреВрд░реНрд╡ рдЗрд╕реЗ рд░реВрдмреА рд╡реЗрдм рд╕рд░реНрд╡рд░ рд╕реЗ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдмрд╛рдж рдореЗрдВ рдлреНрд░реЗрдорд╡рд░реНрдХ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИред



рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЖрдк рд░реИрдХ рдХреЛ рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рдЬрд░реВрд░рддреЛрдВ рдореЗрдВ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рд░реИрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░ рдЖрд╡реЗрджрди рдореЗрдВ рдЖрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рд╣реИ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдирд╛ рд╣реИред

рдкреНрд░рд▓реЗрдЦрди


rack.rubyforge.org/doc

рд░реИрдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ


рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдмрддрд╛рдИ рдЧрдИ рд╕рднреА рдЪреАрдЬрд╝реЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдВрдбреЛрдЬрд╝ рдкрд░ рд╕реНрдерд╛рдкрд┐рдд 1.9.2 рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ( рд╣реЛрд╕реНрдЯ - рдорд╛рд╕реНрдЯрд░ - рдЕрдиреБрдореЛрджрдиред рдкреНрд░рддрд┐ред )

рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд░реИрдХ рд╕реНрдерд╛рдкрд┐рдд рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдВрд╕реЛрд▓ рдЦреЛрд▓реЗрдВ:

# irb --simple-prompt
>> require 'rack'
=> true

рдпрджрд┐ рд░рд┐рдЯрд░реНрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд░реИрдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛, рдЖрдкрдХреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛:

LoadError: no such file to load -- rack

рдпрд╣ рдХреЗрд╡рд▓ рдордгрд┐ рд╕реНрдерд╛рдкрд┐рдд рд░реИрдХ рдХрдорд╛рдВрдб рджреНрд╡рд╛рд░рд╛ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдЦрд░реАрдж рд╡рд╕реНрддреБ рдХрд╛ рддреНрд╡рд░рд┐рдд рджреМрд░рд╛


рдЦрд░реАрдж рд╡рд╕реНрддреБ рдпрд╛рдж рд╣реИ? рд░реВрдмреА рдореЗрдВ, рдмреНрд▓реЙрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЗрдВ рдкреНрд░реЛрдХ рдХреНрд▓рд╛рд╕ рдХреА рд╡рд╕реНрддреБрдУрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреНрд▓рд╛рд╕ рдХреЗ рд▓реИрдореНрдмрдбрд╛ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реИрдореНрдмреНрдбрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдПрдХ рдмреНрд▓реЙрдХ рдорд╛рдгрд┐рдХ рд╡рд┐рдзрд┐ рдХреА рддрд░рд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИред рдФрд░ рдкреНрд░реЛрдХ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдПрдХ рдХреЙрд▓ рд╡рд┐рдзрд┐ рд╣реЛрддреА рд╣реИ, рдЬреЛ рдмреНрд▓реЙрдХ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдмреБрд▓рд╛рддреА рд╣реИред

>> my_rack_proc = lambda {puts 'Rack Intro'}
=> #<Proc:0x1fc9038@(irb):2(lambda)>
>> # method call invokes the block
?> my_rack_proc.call
Rack Intro
=> nil


рд╕рдмрд╕реЗ рд╕рд░рд▓ рд░реИрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ - my_rack_proc


рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рд╣реА рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдорд╛рд░реА рд░реИрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ (рдХреНрд▓рд╛рд╕ рдирд╣реАрдВ) рд╣реИ рдЬреЛ рдХреЙрд▓ рд╡рд┐рдзрд┐ рдХреЗ рдкреНрд░рддрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддреА рд╣реИ рдФрд░ рдПрдХ рддрд░реНрдХ рд▓реЗрддреА рд╣реИ - рдкрд░реНрдпрд╛рд╡рд░рдг ( рдпрд╣ рдкрд░реНрдпрд╛рд╡рд░рдг рднреА рд╣реИ - рд▓рдЧрднрдЧред рдЯреНрд░рд╛рдВрд╕ред )ред рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рд╣реИрд╢ рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рддреАрди рдорд╛рдиреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд╡рд╛рдкрд╕ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП: рдПрдХ рд╕реНрдерд┐рддрд┐ рдХреЛрдб (100 рд╕реЗ рдЕрдзрд┐рдХ рдпрд╛ рдЗрд╕рдХреЗ рдмрд░рд╛рдмрд░), рд╣реЗрдбрд░ (рдПрдХ рд╣реИрд╢), рдФрд░ рдирд┐рдХрд╛рдп (рд╢рд░реАрд░ рдЖрдорддреМрд░ рдкрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рдПрдХ рд╕рд░рдгреА рд╣реИ, рдПрдХ рдЖрд╡реЗрджрди рдЙрджрд╛рд╣рд░рдг, рдпрд╛ рдПрдХ рдлрд╝рд╛рдЗрд▓ рд╣реИред рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╢рд░реАрд░ рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рдзрд┐ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рдХреЗрд╡рд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдорд╛рдиреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП)ред рд╣рдорд╛рд░реЗ рдирдП proc рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдБред

>> my_rack_proc = lambda { |env| [200, {}, ["Hello. The time is #{Time.now}"]] }
=> # <Proc:0x1f4c358@(irb):5(lambda)>

рдЕрдм рдЖрдк my_rack_proc рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

>> my_rack_proc.call({})
=> [200, {}, ["Hello. The time is 2011-10-24 09:18:56 +0530"]]

my_rack_proc рд╣рдорд╛рд░реА рдПрдХрд▓ рдкрдВрдХреНрддрд┐ рд░реИрдХ рд╣реИред

рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдордиреЗ рд╣реЗрдбрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЦрд╛рд▓реА рд╣реИрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣реЗрдбрд░ рдореЗрдВ рдХреБрдЫ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:

>> my_rack_proc = lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello. The time is #{Time.now}"]] }
=> #<Proc:0x1f4c358@(irb):5(lambda)>
>> my_rack_proc.call({})
=> [200, {"Content-Type" => "text/plain"}, ["Hello. The time is 2011-10-24 09:18:56 +0530"]]

рд╣рдо рдХрд┐рд╕реА рднреА рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдирд╛ рд░реИрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВрдбрд▓рд░ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ:

>> Rack::Handler.constants
=> [:CGI, :FastCGI, :Mongrel, :EventedMongrel, :SwiftipliedMongrel, :WEBrick, :LSWS, :SCGI, :Thin]

WEBrick рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ WEBrick рдорд╛рдгрд┐рдХ рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдкрд┐рдд рдПрдХ рд╕рд░реНрд╡рд░ рд╣реИ), рджрд░реНрдЬ рдХрд░реЗрдВ:

>> Rack::Handler::WEBrick
=> Rack::Handler::WEBrick

рдЗрди рд╕рднреА рд╣реИрдВрдбрд▓рд░ рдХреЗ рдкрд╛рд╕ рдПрдХ рд░рди рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рдПрдХ рд░реИрдХ рдПрдкреНрд▓реАрдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рддреА рд╣реИ:

>> Rack::Handler::WEBrick.run my_rack_proc
[2011-10-24 10:00:45] INFO WEBrick 1.3.1
[2011-10-24 10:00:45] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 10:00:45] INFO WEBrick::HTTPServer#start: pid=1788 port=80

рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдкреЗрдЬ рдЦреЛрд▓реЗрдВ рдФрд░ рдЖрдкрдХреЛ рдПрдХ рдкрдВрдХреНрддрд┐ рджреЗрдЦрдиреА рдЪрд╛рд╣рд┐рдП:

  рдирдорд╕реНрдХрд╛рд░ред  рд╕рдордп рд╣реИ 2011-10-24 10:02:20 +0530 


рдиреЛрдЯ: рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреЛрд░реНрдЯ 80 рдкрд░ рдХреБрдЫ рдЪрд▓ рд░рд╣рд╛ рд╣реИ, рддреЛ рдЖрдк рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рджреВрд╕рд░реЗ рдкреЛрд░реНрдЯ рдкрд░ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред
>> Rack::Handler::WEBrick.run my_rack_proc, :Port => 9876
[2011-10-24 11:32:21] INFO WEBrick 1.3.1
[2011-10-24 11:32:21] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 11:32:21] INFO WEBrick::HTTPServer # start: pid = 480 port = 9876

рдПрдХ рдЕрдиреНрдп рд░реИрдХ рдПрдкреНрд▓реАрдХреЗрд╢рди my_method рд╣реИ


рд░реИрдХ-рдЖрд╡реЗрджрди рдЬрд░реВрд░реА рд▓рдВрдмреЛрджрд░ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдПрдХ рд╡рд┐рдзрд┐ рднреА рд╣реЛ рд╕рдХрддреА рд╣реИред

>> def my_method env
>> [200, {}, ["method called"]]
>> end
=> nil
>> Rack::Handler::WEBrick.run method(:my_method)
[2011-10-24 14:32:05] INFO WEBrick 1.3.1
[2011-10-24 14:32:05] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 14:32:05] INFO WEBrick::HTTPServer#start: pid=1644 port=80

рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдореЗрдВ рдЖрдк рдлрд┐рд░ рд╕реЗ рджреЗрдЦреЗрдВрдЧреЗ:

  рд╡рд┐рдзрд┐ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ 

рдСрдмреНрдЬреЗрдХреНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд┐рдзрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдП рдЬрд╛рддреЗ рд╣реИрдВред рд╡реЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд╕реНрддреБ рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝реЗ рд╣реБрдП рд╣реИрдВ (рдФрд░ рди рдХреЗрд╡рд▓ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде)ред рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЗ рднреАрддрд░ рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред Method.call рдПрдХ рдРрд╕рд╛ рддрд░реАрдХрд╛ рд╣реИ рдЬреЛ рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ ( рдУрд╣, рд╣реИрдХ, рд╣реИрдХ ... - рд▓рдЧрднрдЧред ) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдФрд░ рдЙрд╕ рдореВрд▓реНрдп рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдХреЙрд▓ рд╡рд┐рдзрд┐ рд╡рд╛рдкрд╕ рдЖрддреА рд╣реИред

рд░реИрдХрдЕрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


рдЬреЗрдо рд░реИрдХ рдЙрдкрдпреЛрдЧреА рдЯреБрдХрдбрд╝реЛрдВ рдХреЗ рдПрдХ рд╕рдореВрд╣ рдХреЗ рд╕рд╛рде рдЖрддрд╛ рд╣реИ рдЬреЛ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рдЬреАрд╡рди рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддрд╛ рд╣реИред рдЗрди рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд░реИрдХрдЕрдк рд╣реИред

рд░реИрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░реИрдХрдЕрдк рдПрдХ рдЙрдкрдпреЛрдЧреА рдЙрдкрдХрд░рдг рд╣реИред рд░реИрдХрдЕрдк рд╕реНрд╡рдпрдВ рд╣реА рдЙрд╕ рд╡рд╛рддрд╛рд╡рд░рдг рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╡рд╣ рдЪрд▓ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ FastCGI, CGI рдпрд╛ рд╕реНрдЯреИрдВрдб-рдЕрд▓реЛрди рдХреЗ рд╕рд╛рде Mongrel рдпрд╛ WEBrick - рд╕рднреА рдПрдХ рд╣реА рдбреЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рдЪрд▓рд╛рддрд╛ рд╣реИред

рд░реИрдХрдЕрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЗрд╕рдХреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреА рд╣реЛрдЧреАред рдЕрдзрд┐рд╡реЗрд╢рди рджреНрд╡рд╛рд░рд╛, рдЖрдкрдХреЛ рдЗрд╕ рд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рд▓рд┐рдП Ph рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдкреЛрд░реНрдЯ 9292 рдкрд░ рд░реИрдХрдЕрдк рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред

рдЪрд▓реЛ рдПрдХ config.ru рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ:

 run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello. The time is #{Time.now}"]] } 

рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд░рди рд╢рдмреНрдж рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ .call рд╡рд┐рдзрд┐ рдХреЗ рдкреНрд░рддрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реА рд╣рд░ рдЪреАрдЬрд╝ рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

Config.ru рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╕рд╛рде рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд░реИрдХ-рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рджрд░реНрдЬ рдХрд░реЗрдВ:

$ rackup config.ru
[2011-10-24 15:18:03] INFO WEBrick 1.3.1
[2011-10-24 15:18:03] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 15:18:03] INFO WEBrick::HTTPServer # start: pid = 3304 port = 9292

рдЕрдм, рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдкрд░ : 9292 / рд╣рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреЗрдЬ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:

Hello. The time is 2011-10-24 15:18:10 +0530
рдЪрд▓рд┐рдП рд╣рдорд╛рд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ config.ru рдлрд╝рд╛рдЗрд▓ рд╕реЗ my_app.rb рдкрд░ рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ:

 # my_app.rb class MyApp def call(env) [200, {"Content-Type" => "text/html"}, ["Hello Rack Participants"]] end end 

Config.ru рднреА рдмрджрд▓реЗрдВ:
 require './my_app' run MyApp.new 

рдЕрдм рдЖрдк рдлрд┐рд░ рд╕реЗ рдЖрд╡реЗрджрди рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ("рд░реИрдХрдЕрдк config.ru" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдФрд░ рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рдкреГрд╖реНрда рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

Heroku рдкрд░ рд░реИрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рддреИрдирд╛рдд рдХрд░реЗрдВред


(рд▓реЗрдЦ рдХрд╛ рдпрд╣ рдЯреБрдХрдбрд╝рд╛ рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдмреЗрд░рд╣рдореА рд╕реЗ рдХрд╛рдЯрд╛ рдЧрдпрд╛ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЦрд┐рдбрд╝рдХрд┐рдпреЛрдВ рдкрд░ рдЧрд┐рдЯ рдХреА рд╕реНрдерд╛рдкрдирд╛ рдФрд░ рд╣рд░реЛрдХреВ рдкрд░ рддреИрдирд╛рддреА рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рд▓реЗрдЦ рд╕реЗ рдХреЛрдИ рд▓реЗрдирд╛-рджреЗрдирд╛ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдк рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕реЗ рдореВрд▓ - рдЕрдиреБрдорд╛рдирд┐рдд рд░реВрдк рд╕реЗ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ ред )

рд░реИрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


рдпрд╣ рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдХрд┐ рд╕рд░реНрд╡рд░ рдФрд░ рдврд╛рдВрдЪреЗ рдХреЗ рдмреАрдЪ рд░реИрдХ рдХреЛ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрдкрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рд░реИрдХрдЕрдк рдПрдХ рдРрд╕реА рд╡рд┐рдзрд┐ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреА рд╣реИред рдЪрд▓реЛ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд░реИрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рдЖрдкрдиреЗ рджреЗрдЦрд╛ рд╣реЛрдЧрд╛ рдХрд┐ рд╣рд░ рдмрд╛рд░ config.ru рдпрд╛ my_app.rb рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ WEBrick рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдорд┐рдбрд▓рд╡реЗрдпрд░ рд░реИрдХ :: рд░реАрд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕рд╕реЗ рдмрдЪрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред Config.ru рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:

 require './my_app' use Rack::Reloader run MyApp.new 

рдФрд░ my_app.rb:

 # my_app.rb class MyApp def call(env) [200, {"Content-Type" => "text/html"}, ["Hello Rack Participants from across the globe"]] end end 

рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ рдФрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдкреГрд╖реНрда рдЦреЛрд▓реЗрдВред рдЕрдм рджреБрдирд┐рдпрд╛ рднрд░ рд╕реЗ "рд╣реИрд▓реЛ рд░реИрдХ рдкрд╛рд░реНрдЯрд┐рд╕рд┐рдкреЗрдВрдЯреНрд╕!" рд╕реЗ рджреБрдирд┐рдпрд╛ рднрд░ рдХреЗ "рд╣реИрд▓реЛ рд░реИрдХ рдкрд╛рд░реНрдЯрд┐рд╕рд┐рдкреЗрдВрдЯреНрд╕!" рдХреЗ рдЯреЗрдХреНрд╕реНрдЯ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХрд░реЗрдВред рдмреНрд░рд╛рдЙрдЬрд░ рдореЗрдВ рдкреЗрдЬ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рд╡реЗрдм рд╕рд░реНрд╡рд░ рдХреЛ рд░рд┐рд╕реНрдЯрд╛рд░реНрдЯ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдбрд┐рдЯ рдХрд┐рдП рд╣реБрдП рдЯреЗрдХреНрд╕реНрдЯ рдХреЛ рджреЗрдЦреЗрдВрдЧреЗред

рдЕрдкрдиреА рдЦреБрдж рдХреА рдорд┐рдбрд▓рд╡реЗрдпрд░ рд▓рд┐рдЦрдирд╛


рдорд┐рдбрд▓рд╡реЗрдпрд░ рд╣рдореЗрд╢рд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рдЖрдкрдХреЗ рдЖрдВрддрд░рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред

рдЖрдЗрдП рд╕рд░рд▓рддрдо рдорд┐рдбрд▓рд╡реЗрдпрд░ рдмрдирд╛рдПрдВ рдЬреЛ http рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдореБрдЦреНрдп рднрд╛рдЧ рдореЗрдВ рдкрд╛рда рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, MyRackMiddleware рд╡рд░реНрдЧ рдмрдирд╛рдПрдВ:

 class MyRackMiddleware def initialize(appl) @appl = appl end def call(env) end end 

рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдореЗрдВ, рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд┐рдХрд╛рдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо MyRackMiddleware рд╡рд░реНрдЧ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди (appl) рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред

рдЕрдм .call рд╡рд┐рдзрд┐ рдмрджрд▓реЗрдВ:
 def call(env) status, headers, body = @appl.call(env) # we now call the inner application end 

рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдореВрд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд┐рдХрд╛рдп рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ, рдЬрд┐рд╕реЗ рдЕрдм рд╣рдо рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рд░реИрдХ рдЖрдкрдХреЛ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ рдХрд┐ рд╢рд░реАрд░ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛрдЧрд╛ред рдпрд╣ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЬрдм рдЖрдк .each рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд▓реМрдЯрд╛ рд╣реБрдЖ рд╕рдм рдХреБрдЫ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛрдЧрд╛ред рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ .call рд╡рд┐рдзрд┐ рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВ:
 def call(env) status, headers, body = @appl.call(env) append_s = "... greetings from RubyLearning!!" [status, headers, body << append_s] end 

рдЕрдм config.ru рдлрд╝рд╛рдЗрд▓ рдмрджрд▓реЗрдВ:
 require './my_app' require './myrackmiddleware' use Rack::Reloader use MyRackMiddleware run MyApp.new 

рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ "рджреБрдирд┐рдпрд╛ рднрд░ рд╕реЗ рд╣реИрд▓реЛ рд░реИрдХ рдкреНрд░рддрд┐рднрд╛рдЧреА ... RubyLearning рд╕реЗ рд╢реБрднрдХрд╛рдордирд╛рдПрдВ!"

рд░реИрдХ рдФрд░ рд╕рд┐рдирд╛рддреНрд░рд╛


рдЕрдВрдд рдореЗрдВ, рдпрд╣рд╛рдВ рд╕рд╛рдЗрдирдЯреНрд░рд╛ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рд░реИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИред

рдЪрд▓реЛ рдПрдХ рддреБрдЪреНрдЫ рдПрдкреНрд▓рд┐рдХреЗрд╢рди my_sinatra.rb рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рд░реИрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛:
 require 'sinatra' require './rackmiddleware' use RackMiddleware get '/' do 'Welcome to all' end 

рдЕрдм рдЪрд▓реЛ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреНрд▓рд╛рд╕ рдореЗрдВ рд░рдЦрддреЗ рд╣реИрдВ рдЬреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдВрд╕реЛрд▓ рд╕рдордп рдХреЛ рд▓рд┐рдЦреЗрдЧрд╛ред Rackmiddleware.rb рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ:
 class RackMiddleware def initialize(appl) @appl = appl end def call(env) start = Time.now status, headers, body = @appl.call(env) # call our Sinatra app stop = Time.now puts "Response Time: #{stop-start}" # display on console [status, headers, body] end end 

рдЕрдм config.ru рдлрд╝рд╛рдЗрд▓ рдмрджрд▓реЗрдВ:
 require "./my_sinatra" run Sinatra::Application 

( рдЗрд╕рдХреЗ рдмрд╛рдж рдкрд╛рда рдХрд╛ рдмреНрд▓реЙрдХ рдЖрддрд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рд╣рд░реЛрдХрд╛ рдореЗрдВ рдЬрд╛рдПрдВ, рдЧрд┐рдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдЖрджрд┐ред рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдпрд╣ рдЖрдкрдХреЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрдЧрд╛ - рд▓рдЧрднрдЧред )

рдЕрдм, рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдЖрд╡реЗрджрди рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд▓рдЧрднрдЧ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рд╡рд╛рд▓реА рдПрдХ рдкрдВрдХреНрддрд┐ рдХрдВрд╕реЛрд▓ рдкрд░ рд▓рд┐рдЦреА рдЬрд╛рдПрдЧреА:

?[36m2011-10-26T05:40:06+00:00 app[web.1]:?[0m *** Response Time ***: 0.000297385

рд╡рд╣ рд╕рдм рд╣реИред рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ рд░реИрдХ рдореЗрдВ рдЗрд╕ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдХрд╛ рдЖрдирдВрдж рд▓рд┐рдпрд╛ред рд╣реИрдкреНрдкреА рд░реИрдХрд┐рдВрдЧ!

Source: https://habr.com/ru/post/In131429/


All Articles