Writing a middleware for your Sinatra app
Let's suppose you need to perform some task for every action on your controller. Maybe you need to log the result of every call made to your actions, or maybe you need to add a simple auth system, whatever.
The best way to do this is with a middleware. Basically, it'll be an extra layer of code at your controller and you'll not need to implement some weird callback or add more logic to the controller itself.
Follow this tutorial to create a middleware yourself :)
Creating and using your Middleware
Assuming you have a regular controller:
I like to keep my middlewares into a middleware folder. If you want to do the same, remember to add lib/middlewares to auto_load_paths at your environment.rb file:
Your middleware will be just a regular class. No inheritance or inclusion of some obscure model. Take a look:
And you just need to add a single line to your controller to use your brand new middleware!
And bang! Everything should be working fine.
Explanation:
The app variable is your controller itself (in this case, FooController). env is the call made at your controller (the get you or your user is sending).
Calling app.env is the same as reaching your controller with the call your users originally sent (sending the original get HTTP call with all its params to the get '/' action of FooController).
What the code does there is to intercept the original call to the controller and add an extra layer over it (this is what middlewares are supposed to do).
In this layer, we can do whatever we want before allowing things to move forward to the controller (again: we do this calling app.env).
This way, we only REALLY call our controller if our users send the string 'my_secret_token' as a param (yeah, you can access the params of the call at your middleware. Isn't that wonderful?). Otherwise, we simply return 401 (Unauthorized) as a response.
And this will work for every action in your controller without any aditional code :)
Bonus: rescuing controller exceptions at your middleware
Yeah, we can even do that! Check this out:
This way, if our controller raises some kind of weird errors or exception, you can properly rescue it. Easy as that!
With those tips you are able to remove logic from your controller, allowing your code to remain simple, but functional.
Do you have any improvements or suggestion to this tutorial? Have you followed it and it's working fine? Leave a comment!