Renee Core
Routing
Routing in Renee
is different from any web framework you are likely to have used in the past. The syntax is most familiar to Sinatra but allows
for far more flexibility and freedom in the way that routes and actions are defined. In a Renee, routes are defined using the path
, var
, query_string
, extension
, remainder
and request methods.
Request Methods
The bread and butter of Renee are the request verbs reminiscent of Sinatra:
run Renee.core {
get { halt "a get!" }
post { halt "a post!" }
put { halt "a put!" }
delete { halt "a delete!" }
}
These will declare the response to "/" for each of the common request types. Notice the use of the request method to
specify the http verb and the use of halt
inside the block to send back the body of the response.
Path
Path is how Renee describes the basic uri path for a route:
run Renee.core {
path('blog') { ... }
}
All declarations inside that block will start with /blog
. Paths can also be nested within one another:
run Renee.core {
path('blog') {
path('foo') { get { halt "path is /blog/foo" } }
}
}
You can also use exact_path
for more precise path matching and/or part
which doesn't look for leading slashes.
Query String
In addition to defining paths, you may find yourself wanting to describe the state of the query string for a request within the path:
path 'foo' do
query_string 'bar' do
get { halt 'BAR!' }
end
query_string 'baz' do
get { halt 'BAZ!' }
end
end
This will respond to /foo?bar
with "BAR!" and /foo?baz
with "BAZ!". You can also specify query_string in a variety of other ways:
# Check key and value of query param
query_string 'foo=bar' do
post { halt [200,{},'foo'] }
end
# Declare query params as a hash
query :foo => "bar" do
halt 200
end
# Switch based on a query parameter
query :foo do |var|
case var
when 'bar' then halt 200
when 'bar2' then halt 500
end
end
Variables
In Renee, you specify parameters for your request as explicit variables. Variables are declared like this:
path('blog') {
var { |id| get { halt "path is /blog/#{id}" } }
}
You can access the variables (passed into the request) using the local variables yielded to the block. Variables are a powerful way to express expected parameters for a given set of requests. You can specify variables that match a regex:
path('blog') {
var(/\d+/) { |id| get { halt "path is /blog/#{id}" } }
}
and even explicitly cast your variable types:
path('blog') {
var :integer do |id|
get { halt "path is /blog/#{id} and id is an integer" }
end
end
Extensions
You can also use extension
as a way to define formats:
path '/test' do
extension 'html' do
halt 'html'
end
extension 'json' do
halt 'json'
end
end
This will have test.html
respond with 'html' and test.json
respond with 'json'.
Remainder
In the event that no route has been matched, the remainder
keyword makes defining the else case rather easy:
path 'foo' do
path 'bar' do
halt "BAR!"
end
remainder do |rest|
halt "Rest was #{rest}"
end
end
Notice this allows you to handle the cases within a particular route scope and manage them based on the "rest" of the uri yielded in the remainder
block. You
can handle different remainders in all the different path blocks.
Named Routes
Once you have defined your routes, you can then "register" a particular path mapping that to a symbol. This is useful for referencing routes without having to specify the entire path:
run Renee.core {
register(:test, '/test/time')
register(:test_var, '/test/:id')
}
You can then access these using the path
method in a route or template:
path(:test) # => '/test/time'
path(:test_var, :id => 123) # => '/test/123'
Using named routes makes referencing and modifying routes within an application much simpler to manage.
Responding
Responding to a request within a route can be managed with the respond
, halt
, redirect
commands:
Respond
The respond
command makes returning a rack response very explicit, you can respond as if you were constructing a Rack::Response
run Renee {
get { respond!("hello!", 403, "foo" => "bar") }
}
or use the block DSL for convenience:
run Renee {
get { respond! { status 403; headers :foo => "bar"; body "hello!" } }
}
Halt
Halting is the easiest way to render data within a route:
run Renee.core {
get { halt 'easy' }
}
This will return a 200 status code and 'easy' as the body. You can also specify status code and header explicitly in the halt response:
get { halt [200, {}, 'body'] }
This will set the status code to 200, pass no headers and return 'body'. You can also use several variations of halt:
# Return just status code
halt 200
# Return status with symbol
halt :not_found
# Return 200 with body
halt "hello!"
# Return 500 with body
halt 500, "hello!"
Halt is the most straightforward way to control the response for a request.
Redirect
A redirect is a common action within a web route and can be achieved with the convenience method redirect
command:
get {
halt redirect('/hello')
}
You can also specify the status code for the redirect:
get {
halt redirect('/hello', 303)
}