Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Whats Rack?
In the words of the author of Rack Christian Neukirchen: Rack aims to provide a minimal API for connecting web servers supporting Ruby (like W !rick" #ongrel etc$% and Ruby web frameworks (like Rails" &inatra etc$%$ Web frameworks such as &inatra are built on top of Rack or have a Rack interface for allowing web application servers to connect to them$ 'he premise of Rack is simple it (ust allows you to easily deal with )''P re*uests$ )''P is a simple protocol: it basically describes the activity of a client sending a )''P re*uest to a server and the server returning a )''P response$ !oth )''P re*uest and )''P response in turn have very similar structures$ A )''P re*uest is a triplet consisting of a method and resource pair" a set of headers and an optional body while a )''P response is in triplet consisting of a response code" a set of headers and an optional body$ Rack maps closely to this$ A Rack application is a Ruby ob(ect that has a call method" which has a single argument" the environment" (corresponding to a )''P re*uest% and returns an array of + elements" status" headers and body (corresponding to a )''P response%$ Rack includes handlers that connect Rack to all these web application servers (W !rick" #ongrel etc$%$ Rack includes adapters that connect Rack to various web frameworks (&inatra" Rails etc$%$ !etween the server and the framework" Rack can be customi,ed to your applications needs using middleware$ 'he fundamental idea behind Rack middleware is come between the calling client and the server" process the )''P re*uest before sending it to the server" and processing the )''P response before returning it to the client$
A Rack App
Documentation
http:--rack$rubyforge$org-doc-
Installing Rack
/ote that I have Ruby .$0$1 installed on a Windows bo2 and all the programs in this article have been tested using that$ 3et4s check if we already have rack with us$ 5pen a command window and type:
irb --simple-prompt >> require 'rack' => true >>
6es" rack4s already there on your machine$ If rack4s not there you will get an error like:
LoadError: no such file to load -- rack
6ou can install rack by opening a new command window and typing:
gem install rack
A sim le Rack a
As mentioned earlier" our simple Rack application is a Ruby ob(ect (not a class% that responds to call and takes e2actly one argument" the environment$ 'he environment must be a true instance of 5ash$ 'he app should return an Array of e2actly three values: the status code (it must be greater than or e*ual to .88%" the headers (must be a hash%" and the body (the body commonly is an Array of &trings" the application instance itself" or a 9ile:like ob(ect$ 'he body must respond to method each and must only yield 6tring values$% 3et us create our new proc ob(ect$ 'ype:
>> m !rack!proc = lambda " 7en27 81((9 "%9 8:5ello4 ;he time is &";ime4no<%:== % => &'Proc:()*f>c,?-./irb0:?/lambda0> >>
/ow we can call the proc ob(ect my;rack;proc with the call method$ 'ype:
>> m !rack!proc4call/"%0 => 81((9 "%9 8:5ello4 ;he time is 1(**-*(-1> (+:*-:?@ A(?,(:== >>
my#rack# roc is our single line Rack application$ In the above e2ample" we have used an empty hash for headers$ Instead" let4s have something in the header as follows:
>> m !rack!proc = lambda " 7en27 81((9 ":Bontent-; pe: => :te)tCplain:%9 8:5ello4 ;he time is &";ime4no<%:== % => &'Proc:()*f>c,?-./irb0:?/lambda0> >>
/ow we can call the proc ob(ect my;rack;proc with the call method$ 'ype:
>> m !rack!proc4call/"%0 => 81((9 ":Bontent-; pe: => :te)tCplain:%9 8:5ello4 ;he time is 1(**-*(-1> (+:*-:?@ A(?,(:== >>
We can run our Rack application (my#rack# roc% with any of the Rack handlers$ 'o look at the Rack handlers available" in irb type:
>> #ack::5andler4constants => 8:BD$9 :EastBD$9 :Fongrel9 :E2entedFongrel9 :6<iftipliedFongrel9 :GEHrick9 :L6G69 :6BD$9 :;hin= >>
'o get a handler for say W$%rick (the default W$%rick" web application server" that comes along with Ruby%" type:
>> #ack::5andler::GEHrick => #ack::5andler::GEHrick >>
All of these handlers have a common method called run to run all the Rack based applications$
>> #ack::5andler::GEHrick4run m !rack!proc 81(**-*(-1> *(:((:>?= $IEO GEHrick *4,4* 81(**-*(-1> *(:((:>?= $IEO rub *4+41 /1(**-(J-(+0 8i,-@-ming<,1= 81(**-*(-1> *(:((:>?= $IEO GEHrick::5;;P6er2er&start: pid=*J-- port=-(
5pen a browser window and type the url: http:--localhostIn your browser window" you should see a string" something like this:
5ello4 ;he time is 1(**-*(-1> *(:(1:1( A(?,(
Note: If you already have something running at port <8" you can run this app at a different port" say 0<=>$ 'ype:
>> #ack::5andler::GEHrick4run m !rack!proc9 :Port => +-J@ 81(**-*(-1> **:,1:1*= $IEO GEHrick *4,4* 81(**-*(-1> **:,1:1*= $IEO rub *4+41 /1(**-(J-(+0 8i,-@-ming<,1= 81(**-*(-1> **:,1:1*= $IEO GEHrick::5;;P6er2er&start: pid=>-( port=+-J@
5pen a browser window and type the url: http:--localhost:0<=>In your browser window" you should see a string" something like this:
5ello4 ;he time is 1(**-*(-1> *(:(1:1( A(?,(
Another Rack a
" my#method
We declare a method my;method that takes an argument env$ 'he method returns three values$ /e2t type:
>> #ack::5andler::GEHrick4run method/:m !method0 81(**-*(-1> *>:,1:(?= $IEO GEHrick *4,4* 81(**-*(-1> *>:,1:(?= $IEO rub *4+41 /1(**-(J-(+0 8i,-@-ming<,1= 81(**-*(-1> *>:,1:(?= $IEO GEHrick::5;;P6er2er&start: pid=*@>> port=-(
5pen a browser window and type the url: http:--localhostIn your browser window" you should see something like this:
method called
ob(ects are created by Object&method$ 'hey are associated with a particular ob(ect (not (ust with a class%$ 'hey may be used to invoke the method within the ob(ect$ 'he Fethod4call method invokes the method with the specified arguments" returning the method4s return value$
Fethod
'sing racku
'he rack gem comes with a bunch of useful stuff to make life easier for a rack application developer$ rackup is one of them$
rackup is a useful tool for running Rack applications$ rackup automatically figures out the environment it is run in" and runs your application as 9astABI" ABI" or standalone with #ongrel or W !rick all from the same configuration$ 'o use rackup" you4ll need to supply it with a rackup config file$ !y convention" you should use $ru e2tension for a rackup config file$ &upply it a run Rack5b(ect and you4re ready to go:
K rackup config4ru
!y default" rackup will start a server on port 0101$ 'o view rackup help" open a command window and type:
K rackup --help
'his file contains run" which can be called on anything that responds to a 4call$ 'o run our rack app" in the same folder that contains config$ru" type:
K rackup config4ru 81(**-*(-1> *?:*-:(,= $IEO GEHrick *4,4* 81(**-*(-1> *?:*-:(,= $IEO rub *4+41 /1(**-(J-(+0 8i,-@-ming<,1= 81(**-*(-1> *?:*-:(,= $IEO GEHrick::5;;P6er2er&start: pid=,,(> port=+1+1
5pen a browser window and type the url: http:--localhost:0101In your browser window" you should see something like this:
5ello4 ;he time is 1(**-*(-1> *?:*-:*( A(?,(
Press Ctrl&C to stop the W$%rick server$ /ow let4s move our application from the config$ru file to my;app$rb file as follows:
& m !app4rb class F Lpp def call en2 81((9 ":Bontent-; pe: => :te)tChtml:%9 8:5ello #ack Participants:== end end
'o run our rack app" in the same folder that contains config$ru" type:
rackup config4ru 81(**-*(-1? (@:*-:*@= $IEO 81(**-*(-1? (@:*-:*@= $IEO 81(**-*(-1? (@:*-:*@= $IEO
5pen a browser window and type the url: http:--localhost:0101In your browser window" you should see something like this:
5ello #ack Participants
s to )eroku
We shall now download and install Bit$ 'he precompiled packages are available here: http:--git$or$c,&elect the relevant package for your operating system$ Bit still has some issues on the Windows platform but for normal usage the msysgit package shouldn4t let you down$ Download and install it from the url: http:--code$google$com-p-msysgit-downloads-list &elect the current version available$ Install by running the E installer$ When asked" it is recommended for Windows users to use the FGse Bit !ash onlyH option$ Please ensure that you are connected to the internet and then create an account on )eroku (obviously do this only once% if you don4t have one http:--heroku$com-signup$ 5pen a new command window to install the )eroku gem file$ 'ype:
gem install heroku
/e2t" create a new folder" say rackheroku$ Assuming that you have Bit installed" open a !ash shell in that folder$ 6ou now need to identify yourself to Bit (you need to do this only once%$ With the bash shell still open type in the following:
git config --global user4name :Mour name here: git config --global user4email :Mour email id:
Bit does not allow accented characters in user name$ 'his will set the info stored when you commit to a Bit repository$ Bit has now been set up$ 'he first step in using Bit is to create your &&) Iey$ 'his will be used to secure communications between your machine and other machines" and to identify your source code changes$ (If you already have an &&) key for other reasons" you can use it here" there is nothing Bit:specific about this$%
>
'o create our ssh key" open a new command window and type:
K ssh-ke gen -B :username.email4com: -t rsa
(with your own email address" of course%$ Accept the default key file location$ When prompted for a passphrase" make one up and enter it$ If you feel confident that your own machine is secure" you can use a blank passphrase" for more convenience and less security$ /ote where it told you it stored the file$ 5n my Windows bo2" it was stored in FA:JDocuments and &ettingsJAJ$sshJH$ #emori,e your passphrase carefully$ If you forget it" you will /5' be able to recover it$ 5pen the public file id;rsa$pub with a te2t editor$ 'he te2t in there is your Fpublic &&) keyH$ Gpload your public key (do it only once%:
K heroku ke s:add
6ou4ll be prompted for your username and password the first time you run a heroku command? they4ll be saved on K-$heroku-credentials so you won4t be prompted on future runs$ It will also upload your public key to allow you to push and pull code$ In order for )eroku to know what to do with your Rack app" create a config$ru (ru stands for Rack up% in the rackheroku folder$ 'he contents are:
require '4Cm !app' run F Lpp4ne<
Also" copy the my;app$rb file to the rackheroku folder$ It4s contents are:
& m !app4rb class F Lpp def call en2 81((9 ":Bontent-; pe: => :te)tChtml:%9 8:5ello #ack Participants:== end end
Alose the command window$ /e2t" we will install the re*uired gems (if any% via bundler$ In the already open Bit !ash shell for folder rackheroku type:
K bundle init Griting ne< Demfile to c:CrackherokuCDemfile
dit the created Bemfile with your preferred te2t editor to let it look like this:
source :http:CCrub gems4org: gem 'rack'
/ow we need to tell !undler to check if we4re missing the gems our application depends on" if so" tell it to install them$ In your open !ash shell type:
K bundle check ;he Demfile's dependencies are satisfied
'his will ensure all gems specified on Bemfile" together with their dependencies" are available for your application$ Running Fbundle installH will also generate a FBemfile$lockH file$ 'he Bemfile$lock ensures that your deployed versions of gems on )eroku match the version installed locally on your development machine$ /e2t we set up our local app to use Bit$ 'ype:
K git init K git add 4 K git commit -m :#ack app first commit:
'he app has been created and two GR3s are provided$ 5ne is for the web face of your new app i$e$ http:--*uiet:winter:+=@.$heroku$com- If you visit that GR3 now" you4ll see a standard welcome page" until you push your application up$ 'he other one is for the Bit repository that you will push your code to$ /ormally you would need to add this as a git remote? the Fheroku createH command has done this for you automatically$ Do note that the output from the create command will be different for each one of you$ /ow let us deploy our code to )eroku$ 'ype:
git push heroku master
5ur app is now deployed to )eroku$ 5pen a new browser window and type http:--rackheroku$heroku$comIn the browser window" you should see:
5ello #ack Participants from across the globe
<
In the same folder" we have the my;app$rb file$ It4s contents are:
& m !app4rb class F Lpp def call en2 81((9 ":Bontent-; pe: => :te)tChtml:%9 8:5ello #ack Participants from across the globe:== end end
'o run our rack app" in the same folder that contains config$ru" type:
K rackup config4ru
5pen a browser window and type the url: http:--localhost:0101-$ In your browser window" you should see something like this:
5ello #ack Participants from across the globe
#odify my;app$rb and instead of F)ello Rack Participants from across the globeH type F)ello Rack Participants from across the worldL Refresh the browser window and you should see:
5ello #ack Participants from across the <orldN
'here was no need to re:start the W !rick server$ 6ou can now press Ctrl&C to stop the W$%rick server$
9or all practical purposes" a middleware is a rack application that wraps up an inner application$ 5ur middleware is going to do something very simple$ We will append some te2t to the body being sent by our inner application$ 3et us write our own middleware$ We will create a middleware class called F #ackFiddle<are$ )ere4s the skeleton program:
class F #ackFiddle<are def initialiOe/appl0 .appl = appl end def call/en20 end end
In the code above" to get the original body" we initiali,e the class F #ackFiddle<are by passing in the inner application (appl%$ /e2t we need to call this appl:
def call/en20 status9 headers9 bod application end = .appl4call/en20 & <e no< call the inner
In the above code" we now have access to the original body" which we can now modify$ Rack does not guarantee you that the body would be a string$ It could be an ob(ect too$ )owever" we are guaranteed that if we call 4each on the body" everything it returns will be a string$ 3et4s use this in our call method:
def call/en20 status9 headers9 bod = .appl4call/en20 append!s = :444 greetings from #ub LearningNN: 8status9 headers9 bod '' append!s= end
.8
81((9 ":Bontent-; pe: => :te)tChtml:%9 8:5ello #ack Participants from across the globe:== end end
'o run our rack app" in the same folder that contains config$ru" type:
K rackup config4ru
5pen a browser window and type the url: http:--localhost:0101-$ In your browser window" you should see something like this:
5ello #ack Participants from across the globe444 greetings from #ub LearningNN
&inatra can use Rack middleware$ 5ur trivial middleware class will intercept the re*uest from the user" calculate and display the response time on the console and pass on the unaltered re*uest to the &inatra app$ In the folder racksinatra write the middleware class namely rackmiddle<are4rb$
class #ackFiddle<are def initialiOe/appl0 .appl = appl end def call/en20 start = ;ime4no< status9 headers9 bod = .appl4call/en20 & call our 6inatra app stop = ;ime4no< puts :#esponse ;ime: &"stop-start%: & displa on console 8status9 headers9 bod = end end
..
In order for )eroku to know what to do with our &inatra app" create a config$ru in the folder racksinatra:
require :4Cm !sinatra: run 6inatra::Lpplication
/ow open a Bit !ash shell for folder racksinatra and type:
K bundle init
dit the created Bemfile with your preferred te2t editor to let it look like this:
source :http:CCrub gems4org: gem 'sinatra'
5n my machine it showed:
Breating <arm-<inter-@J-?444 done9 stack is bamboo-mri-*4+41 http:CC<arm-<inter-@J-?4heroku4comC 7 git.heroku4com:<arm-<inter-@J-?4git Dit remote heroku added
'he app is now running on )eroku$ 6ou can take a look at it" in your browser type: http:--racksinatra$heroku$com-$ 'o check whether the MMM Response 'ime MMM: has been displayed on the )eroku console" type:
K heroku logs -s app -n ?
where -s app shows the output from your app and -n ? retrieves C log lines$ 9or me it showed:
38,@m1(**-*(-1@;(?:>(:(@A((:(( app8<eb4*=:38(m PPP #esponse ;ime PPP: (4(((1+J,-?
'hat4s it$ I hope you liked this introductory article on Rack$ )appy RackingLL &atish 'alim is an author and founder of Ruby3earning$com and Ruby3earning$org where over +C888 participants have learnt Ruby programming from across the globe$
.+
'his class is not a Rack application$ It demonstrates what a triplet looks like$ 'he first element is the )''P response code$ 'he second is a hash of headers$ 'he third is an enumerable ob(ect representing the body$ We can use our hello world class to create a simple rack app$ We know that we need to create an ob(ect that responds to call$ call takes one argument: the rack environment$ WeQll come back to the en2 later$
class 5elloGorldLpp def self4call/en20 5ello<Gorld4ne<4response end end
IQve made a simple class that implements call$ It returns the response from the 5elloGorld class$ /ow we need to put this online$ We have implemented one side of the wall$ /ow we need write the other side$ Rack includes a 6er2er class$ 'his is the simplest way to serve rack applications$ It includes daemoni,ation and things like that$ It works but itQs not meant from production applicationsL 3etQs create a simple ruby script to serve 5elloGorldLpp
& hello!<orld4rb require 'rack' require 'rackCser2er' class 5elloGorld def response 81((9 "%9 '5ello Gorld'= end end class 5elloGorldLpp def self4call/en20 5elloGorld4ne<4response end end
.@
&imply open http:CClocalhost:-(-( and youQll see P)ello WorldP in the browser$ ItQs not fancy but you (ust wrote your first rack appL We didnQt write our own server and thatQs ok$ #atter of fact" thatQs fantastic$ 5dds are you will never need to write your own server$ 'here are plenty of servers to choose from: 'hin" Gnicorn" Rainbows" Boliath" Puma" and Passenger$ 6ou donQt want to write those$ 6ou want to write applications$ 'hatQs what we wrote$
Env
I skipped over over what en2 is in the previous section$ 'hatQs because we didnQt need it yet$ 'he en2 is a 5ash that meets the rack spec$ 6ou can read the spec here$ It defines incoming information$ 5utgoing data must be triplets$ 'he en2 gives you access to incoming headers" host info" *uery string and other common information$ 'he en2 is passed to the application which decides what to do$ 5ur 5elloGorldLpp didnQt care about it$ 3etQs update our 5elloGorldLpp to interact with incoming information$
class 5elloGorldLpp def self4call/en20 81((9 "%9 :5ello Gorld4 Mou said: &"en28'QRE#M!6;#$ID'=%:= end end #ack::6er2er4start :app => 5elloGorldLpp
/ow visit http:CClocalhost:-(-(3message=foo and youQll see PmessageRfooP on the page$ If your more curious about en2 you can do this:
class En2$nspector def self4call/en20 81((9 "%9 en24inspect= end end #ack::6er2er4start :app => En2$nspector
)ereQs the tl?dr of what basic en2 looks like$ ItQs (ust a standard )ash instance$
" :6E#SE#!6OE;GL#E:=>:thin *4>4* codename Bhromeo:9 :6E#SE#!ILFE:=>:localhost:9 :rack4input:=>&'6tring$O:()((Jfa*bce(,+f->9 :rack42ersion:=>8*9 (=9 :rack4errors:=>&'$O:'6;TE##>>9 :rack4multithread:=>false9
.C
:rack4multiprocess:=>false9 :rack4run!once:=>false9 :#EQRE6;!FE;5OT:=>:DE;:9 :#EQRE6;!PL;5:=>:Cfa2icon4ico:9 :PL;5!$IEO:=>:Cfa2icon4ico:9 :#EQRE6;!R#$:=>:Cfa2icon4ico:9 :5;;P!SE#6$OI:=>:5;;PC*4*:9 :5;;P!5O6;:=>:localhost:-(-(:9 :5;;P!BOIIEB;$OI:=>:keep-ali2e:9 :5;;P!LBBEP;:=>:PCP:9 :5;;P!R6E#!LDEI;:=> :FoOillaC?4( /FacintoshU $ntel Fac O6 V *(!J!>0 LppleGebWitC?,@4** /W5;FL9 like Decko0 BhromeC1(4(4**,14>J 6afariC?,@4**:9 :5;;P!LBBEP;!EIBOT$ID:=>:gOip9deflate9sdch:9 :5;;P!LBBEP;!LLIDRLDE:=>:en-R69enUq=(4-:9 :5;;P!LBBEP;!B5L#6E;:=>:$6O---?+-*9utf--Uq=(4J9PUq=(4,:9 :5;;P!BOOW$E:=> :!gauges!unique! ear=*U !gauges!unique!month=*:9 :DL;EGLM!$I;E#ELBE:=>:BD$C*41:9 :6E#SE#!PO#;:=>:-(-(:9 :QRE#M!6;#$ID:=>::9 :6E#SE#!P#O;OBOL:=>:5;;PC*4*:9 :rack4url!scheme:=>:http:9 :6B#$P;!ILFE:=>::9 :#EFO;E!LTT#:=>:*1J4(4(4*:9 :as nc4callback:=>&'Fethod: ;hin::Bonnection&post!process>9 :as nc4close:=>&'E2entFachine::TefaultTeferrable:()((Jfa*bce,?b-%
6ou may have noticed that the en2 doesnQt do any fancy parsing$ 'he *uery string wasnQt a hash$ It was the string$ 'he en2 is raw data$ I like this design principle a lot$ Rack is very simple to understand and use$ If you wanted you could only work with hashes and triplets$ )owever thatQs (ust tedious$ Aomple2 applications need abstractions$ nter #ack::#equest and #ack::#esponse$
Abstractions
is an abstraction around the en2 hash$ It provides access to thinks like cookies" P5&' paramters" and other common things$ It removes boiler plate code$ )ereQs an e2ample$
#ack::#equest class 5elloGorldLpp def self4call/en20 request = #ack::#equest4ne< en2 request4params & contains the union of DE; and PO6; params request4)hr3 & requested <ith LXLV require4bod & the incoming request $O stream if request4params8'message'= 81((9 "%9 request4params8'message'== else 81((9 "%9 '6a something to meN'= end end end
is simply a pro2y for the en2 hash$ 'he underlying en2 hash is modified so keep that in mind$
#ack::#equest
.>
is an abstraction around generating response triplets$ It simplifies access to headers" cookies" and the body$ )ereQs an e2ample:
#ack::#esponse class 5elloGorldLpp def self4call/en20 response = #ack::#esponse4ne< response4<rite '5ello Gorld' & <rite some content to the bod response4bod = 8'5ello Gorld'= & or set it directl response8'V-Bustom-5eader'= = 'foo' response4set!cookie 'bar'9 'baO' response4status = 1(1 response4finish & return the generated triplet end end
'hese are basic abstractions$ 'hey donQt re*uire much e2planation$ 6ou can learn more about them by reading the documentation$ /ow that we have some basic abstractions we can start to make more comple2 applications$ ItQs hard to make an application when all the logic is contained in one class$ Applications are always composed of different classes$ ach class has a single responsibility$ 'his is the &RP (&ingle Responsibility Principle%$ 'hese discrete chunks are called PmiddlewareP$
Middleware
Rack applications are simply ob(ects that respond to call$ We can do whatever we want inside call" for instance we can delegate to another class$ )ereQs an e2ample:
class ParamsParser def initialiOe/app0 .app = app end def call/en20 request = #ack::#equest4ne< en2 en28'params'= = request4params app4call en2 end end class 5elloGorldLpp def self4call/en20 parser = ParamsParser4ne< self en2 = parser4call en2 & en28'params'= is no< set to a hash for all the input paramters 81((9 "%9 en28'params'=4inspect= end end
I admit this e2ample is *uite contrived$ 6ou want not do this in practice$ 'he point is to illustrate that you can manipulate env (or response%$ 6ou can create a middleware stack as deep as you like$ ach middleware simply calls the ne2t one and returns its value$ 'his is an e2ample of the builder pattern$ Aomposing Rack applications is so common (and re*uired%
.=
that Rack includes a class to make this easy$ !efore we move to the ne2t step" letQs define what a middleware looks like:
class Fiddle<are def initialiOe/app0 .app = app end & ;his is a :null: middl<are because it simpl calls the ne)t one4 & Ge can manipulate the input before calling the ne)t middle<are & or manipulate the response before returning up the chain4 def call/en20 .app4call en2 end end
IQm not going to cover what those middlewares do because thatQs not important$ 'his is an e2ample of how you can build up functionality in applications$ #iddlewares are very powerful$ 6ou can add manipulate incoming data before hitting the ne2t one or modify the response from an e2isting one$ 3etQs create some for practice$
class EnsureXson#esponse def initialiOe/app0 .app = app end & 6et the 'Lccept' header to 'applicationCjson' no matter <hat4 & 5opefull the ne)t middle<are respects the accept header :0 def call/en20 en28'5;;P!LBBEP;'= = 'applicationCjson' .app4call en2
.<
end end class ;imer def initialiOe/app0 .app = app end def call/en20 before = ;ime4no< status9 headers9 bod
= .app4call en2
WeQve (ust written our own middeware and learned how to generate a runnable application with a middleware stack$ 'his is how rack apps are written in practice$ /ow onto the final piece of the pu,,le: config4ru
Rackup
6ou may have seen the rackup command referenced before$ ItQs provided by the rack gem$ It provides a simple way to start a web process using one of the rack servers installed on the system$ It looks for config4ru by default$ config4ru defines what ruby code the server should call$ ItQs wrapped in a #ack::Huilder as shown before$ )ereQs all the work weQve done up to now in config4ru
& config4ru & 5elloGorldLpp defintion & EnsureXson#esponse defintion & ;imer definition use ;imer use EnsureXson#esponse run 5elloGorldLpp
/ow navigate into the correct directory and run: rackup and youQll see:
K rackup >> ;hin <eb ser2er /2*4>4* codename Bhromeo0 >> Fa)imum connections set to *(1> >> Listening on (4(4(4(:-(-(9 B;#LAB to stop
.0
Rackup will prefer better servers like 'hin over We!rick$ 'hereQs nothing super fancy going on here$ 'he code inside config4ru is evaluated and built using a #ack::Huilder which generates an API compliant ob(ect$ 'he ob(ect is passed to the rack server ('hin% in this case$ 'hin puts the app online$
'he middlewares are not declared e2plicitly in config4ru$ Rails applications create their own middleware chains from different configuration files$ 'he application instance delegates call to the middleware chain$ )ereQs an e2ample config4ru for a rails app:
& ;his file is used b #ack-based ser2ers to start the application4 !!E$LE!!0
6ou know that E)ample::Lpplication must have a call method$ )ereQs the implementation of this method from +$1 stable:
& #ails::Lpplication9 #ails::Lpplication ' #ails::Engine def call/en20 en28:O#$D$ILL!ERLLPL;5:= = build!original!fullpath/en20 super/en20 end & #ails::Engine
18
& the super class method def call/en20 app4call/en24mergeN/en2!config00 end & app method in the super class def app .app 77= begin config4middle<are = config4middle<are4merge!into/default!middle<are!stack0 config4middle<are4build/endpoint0 end end
1.