Discussion:
Middleware or before hook?
Tim Uckun
2017-09-24 07:57:54 UTC
Permalink
I am writing an API in sinatra. It will be a pure JSON api so I need to
parse the body as JSON and I am wondering whether it's more efficient to do
that with a middleware or as a before hook?

Also a question about the general setup. I will have public paths and
private paths and I will be using JWT. One approach is to create a
namespace for the private and as a before or use setting make sure the JWT
exists and is valid. Another approach would be to create two apps one for
the private and one for the public and mount them on different paths. Is
one way more efficient than the other?

Finally. How about I group similar functionality into a separate app and
have many apps each of which inherits from a base app but is mounted on
different paths. Does Sinatra initialize all the classes on every request
or only initialize them when the mounted path is hit?

Thanks.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
c***@gmail.com
2017-09-24 17:17:34 UTC
Permalink
It will be a pure JSON api so I need to parse the body as JSON and I am
wondering whether it's more efficient to do that with a middleware or as a
before hook?

If you care a lot about efficiency, you might want to try Hobby
<https://github.com/ch1c0t/hobby>. According to this benchmark
<https://github.com/luislavena/bench-micro#have-some-numbers-around>, Hobby
is a lot faster than Sinatra.
Also, hobby-json <https://github.com/ch1c0t/hobby-json> makes working with
JSON more concise.

As the author of Hobby, I am obviously biased, but I will be happy to help
you get started if you decide to give it a try.
I am writing an API in sinatra. It will be a pure JSON api so I need to
parse the body as JSON and I am wondering whether it's more efficient to do
that with a middleware or as a before hook?
Also a question about the general setup. I will have public paths and
private paths and I will be using JWT. One approach is to create a
namespace for the private and as a before or use setting make sure the JWT
exists and is valid. Another approach would be to create two apps one for
the private and one for the public and mount them on different paths. Is
one way more efficient than the other?
Finally. How about I group similar functionality into a separate app and
have many apps each of which inherits from a base app but is mounted on
different paths. Does Sinatra initialize all the classes on every request
or only initialize them when the mounted path is hit?
Thanks.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Tim Uckun
2017-09-25 09:15:39 UTC
Permalink
That didn't answer my questions :)

I have been working on and off for a couple of weeks on this I must say
it's been pretty frustrating. I think I finally got enough plumbing done to
try and actually start writing my app now but it took me way longer than I
ever thought it would. At this point if I am going to throw away all this
work and go someplace else I will either go with rails or maybe even a
completely different language like elixir and phoenix or golang or
something.

Up to this point almost everything I have done has been to try and get a
tiny bit of the functionality I get in rails. I am still missing a lot so
more work to do yet! Although I appreciate the speed and efficiency of
sinatra at this point I would not reccomend these types of micro frameworks
for writing anything more than a trivial app. Even then I would say the
tooling you get with rails is probably enough to choose it over something
smaller and more efficient.

Maybe I should have started with padrino. I think that would have saved me
a lot of work.
Post by c***@gmail.com
It will be a pure JSON api so I need to parse the body as JSON and I am
wondering whether it's more efficient to do that with a middleware or as a
before hook?
If you care a lot about efficiency, you might want to try Hobby
<https://github.com/ch1c0t/hobby>. According to this benchmark
<https://github.com/luislavena/bench-micro#have-some-numbers-around>,
Hobby is a lot faster than Sinatra.
Also, hobby-json <https://github.com/ch1c0t/hobby-json> makes working
with JSON more concise.
As the author of Hobby, I am obviously biased, but I will be happy to help
you get started if you decide to give it a try.
I am writing an API in sinatra. It will be a pure JSON api so I need to
parse the body as JSON and I am wondering whether it's more efficient to do
that with a middleware or as a before hook?
Also a question about the general setup. I will have public paths and
private paths and I will be using JWT. One approach is to create a
namespace for the private and as a before or use setting make sure the JWT
exists and is valid. Another approach would be to create two apps one for
the private and one for the public and mount them on different paths. Is
one way more efficient than the other?
Finally. How about I group similar functionality into a separate app and
have many apps each of which inherits from a base app but is mounted on
different paths. Does Sinatra initialize all the classes on every request
or only initialize them when the mounted path is hit?
Thanks.
--
You received this message because you are subscribed to the Google Groups
"sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Anatoly Chernow
2017-09-25 11:54:11 UTC
Permalink
Although I appreciate the speed and efficiency of sinatra at this point I
would not reccomend these types of micro frameworks for writing anything
more than a trivial app. Even then I would say the tooling you get with
rails is probably enough to choose it over something smaller and more
efficient.

Respectfully, I disagree with that. In my opinion, many Rails applications
can benefit from using Hobby.

The value it brings lay not only in "speed and efficiency", but in higher
code reusability. You can create only one Hobby application, and replace
many Rails controllers by instantiating that Hobby application with
different arguments(different models, for example).

Hence, in a long run it will actually save a lot of time and efforts.
That didn't answer my questions :)
I have been working on and off for a couple of weeks on this I must say
it's been pretty frustrating. I think I finally got enough plumbing done to
try and actually start writing my app now but it took me way longer than I
ever thought it would. At this point if I am going to throw away all this
work and go someplace else I will either go with rails or maybe even a
completely different language like elixir and phoenix or golang or
something.
Up to this point almost everything I have done has been to try and get a
tiny bit of the functionality I get in rails. I am still missing a lot so
more work to do yet! Although I appreciate the speed and efficiency of
sinatra at this point I would not reccomend these types of micro frameworks
for writing anything more than a trivial app. Even then I would say the
tooling you get with rails is probably enough to choose it over something
smaller and more efficient.
Maybe I should have started with padrino. I think that would have saved me
a lot of work.
Post by c***@gmail.com
It will be a pure JSON api so I need to parse the body as JSON and I am
wondering whether it's more efficient to do that with a middleware or as a
before hook?
If you care a lot about efficiency, you might want to try Hobby
<https://github.com/ch1c0t/hobby>. According to this benchmark
<https://github.com/luislavena/bench-micro#have-some-numbers-around>,
Hobby is a lot faster than Sinatra.
Also, hobby-json <https://github.com/ch1c0t/hobby-json> makes working
with JSON more concise.
As the author of Hobby, I am obviously biased, but I will be happy to
help you get started if you decide to give it a try.
I am writing an API in sinatra. It will be a pure JSON api so I need to
parse the body as JSON and I am wondering whether it's more efficient to do
that with a middleware or as a before hook?
Also a question about the general setup. I will have public paths and
private paths and I will be using JWT. One approach is to create a
namespace for the private and as a before or use setting make sure the JWT
exists and is valid. Another approach would be to create two apps one for
the private and one for the public and mount them on different paths. Is
one way more efficient than the other?
Finally. How about I group similar functionality into a separate app
and have many apps each of which inherits from a base app but is mounted on
different paths. Does Sinatra initialize all the classes on every request
or only initialize them when the mounted path is hit?
Thanks.
--
You received this message because you are subscribed to the Google Groups
"sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the
Google Groups "sinatrarb" group.
To unsubscribe from this topic, visit https://groups.google.com/d/
topic/sinatrarb/7_ZsExsAFB8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
'Mike Pastore' via sinatrarb
2017-09-25 18:03:18 UTC
Permalink
Post by Tim Uckun
I have been working on and off for a couple of weeks on this I must say
it's been pretty frustrating. I think I finally got enough plumbing done to
try and actually start writing my app now but it took me way longer than I
ever thought it would. At this point if I am going to throw away all this
work and go someplace else I will either go with rails or maybe even a
completely different language like elixir and phoenix or golang or
something.
Up to this point almost everything I have done has been to try and get a
tiny bit of the functionality I get in rails. I am still missing a lot so
more work to do yet! Although I appreciate the speed and efficiency of
sinatra at this point I would not reccomend these types of micro frameworks
for writing anything more than a trivial app. Even then I would say the
tooling you get with rails is probably enough to choose it over something
smaller and more efficient.
Maybe I should have started with padrino. I think that would have saved me
a lot of work.
There is a steep learning curve, and yes, you pretty much have to do
everything yourself. It's helpful to keep in mind that Sinatra really is
just a thin DSL over Rack. It's a couple thousand SLOC vs. tens (hundreds?)
of thousands SLOC for Rails.

Fortunately, there are a lot of extensions for and of Sinatra that are
available to help with this problem. I would highly recommending exploring
Padrino and other options and alternatives. Or keep chipping away at it if
you have the time, it's a great learning experience!
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Tim Uckun
2017-09-25 22:29:59 UTC
Permalink
I already know ruby and the ecosystem pretty well so for me it wasn't so
much the learning curve as the lack of plumbing and trying to figure out
how to arrange the app. With rails everything is ready to go, the paths are
included in proper order, rake tasks are there for everything you need,
tests are integrated, and of course there is copious documentation and a
wealth of gems to do everything you need. Just pop in devise and a couple
of other plugins and you are ready to go.

What took me a long time as trying to hunt down the bits and pieces I need
and putting them in the right place.

BTW the namespace feature of sinatra conflicts with rake namespaces. I
found a workaround but just wanted to let you know in case you didn't.



On Tue, Sep 26, 2017 at 7:03 AM, 'Mike Pastore' via sinatrarb <
Post by 'Mike Pastore' via sinatrarb
Post by Tim Uckun
I have been working on and off for a couple of weeks on this I must say
it's been pretty frustrating. I think I finally got enough plumbing done to
try and actually start writing my app now but it took me way longer than I
ever thought it would. At this point if I am going to throw away all this
work and go someplace else I will either go with rails or maybe even a
completely different language like elixir and phoenix or golang or
something.
Up to this point almost everything I have done has been to try and get a
tiny bit of the functionality I get in rails. I am still missing a lot so
more work to do yet! Although I appreciate the speed and efficiency of
sinatra at this point I would not reccomend these types of micro frameworks
for writing anything more than a trivial app. Even then I would say the
tooling you get with rails is probably enough to choose it over something
smaller and more efficient.
Maybe I should have started with padrino. I think that would have saved
me a lot of work.
There is a steep learning curve, and yes, you pretty much have to do
everything yourself. It's helpful to keep in mind that Sinatra really is
just a thin DSL over Rack. It's a couple thousand SLOC vs. tens (hundreds?)
of thousands SLOC for Rails.
Fortunately, there are a lot of extensions for and of Sinatra that are
available to help with this problem. I would highly recommending exploring
Padrino and other options and alternatives. Or keep chipping away at it if
you have the time, it's a great learning experience!
--
You received this message because you are subscribed to the Google Groups
"sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
'Mike Pastore' via sinatrarb
2017-09-27 16:32:46 UTC
Permalink
Post by Tim Uckun
BTW the namespace feature of sinatra conflicts with rake namespaces. I
found a workaround but just wanted to let you know in case you didn't.
That seems... unlikely. Do you have an example of such a conflict?
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Tim Uckun
2017-09-28 00:40:26 UTC
Permalink
My app is the example :)

In my app I have the following file in config/environment


APP_ENV = ENV['APP_ENV'] ||= ENV['RACK_ENV'] ||= ENV['RAILS_ENV']
||= 'development'
#This is the "real" app root. It will work even when this file is
included in specs and elsewhere
APP_ROOT = File.expand_path('../..', __FILE__)

require 'bundler'
Bundler.require :default, APP_ENV.to_sym

#dotenv will not override the actual env vars...
Dotenv.load(File.join(APP_ROOT, '.env.development')) if APP_ENV != 'production'


I include this file in my Rakefile as well as my spec_helper and app.rb

I ran into problems trying to run rake tasks so I googled around a bit and
found this workaround in my gemfile.

gem 'sinatra-contrib', require: false




On Thu, Sep 28, 2017 at 5:32 AM, 'Mike Pastore' via sinatrarb <
Post by 'Mike Pastore' via sinatrarb
Post by Tim Uckun
BTW the namespace feature of sinatra conflicts with rake namespaces. I
found a workaround but just wanted to let you know in case you didn't.
That seems... unlikely. Do you have an example of such a conflict?
--
You received this message because you are subscribed to the Google Groups
"sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
'Mike Pastore' via sinatrarb
2017-09-28 01:28:35 UTC
Permalink
Post by Tim Uckun
My app is the example :)
That doesn't really illustrate the issue, but I was able to google around
and find an old issue
<https://github.com/sinatra/sinatra-contrib/issues/111> that I think is the
same thing as you're dealing with. Here's a simple Rakefile that clearly
shows the conflict (just run "rake" in the same directory to see the
output):

require 'sinatra'
require 'sinatra/namespace'

p method(:namespace).source_location # =>
["/Users/mwp/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/sinatra-2.0.0/lib/sinatra/base.rb",
1921]

# I can't do a Rake namespace here!

task(:default) {}

It's a weird issue that I've never run into because I almost always use
modular mode (subclassing Sinatra::Application or Sinatra::Base). In this
mode, you require "sinatra/base", not "sinatra", and Sinatra doesn't set up
the delegation from the top-level context to itself. (In "classic" mode,
Sinatra::Namespace just piggybacks off this mechanism to add its :namespace
method to the list of delegated methods.)

I know you already have a workaround—and there's an around-alias workaround
described in that issue report—but I'd like to offer a few more options:

1. If you're not using any sinatra-contrib features, just remove it from
your Gemfile.
2. If you don't need Sinatra::Namespace but you're using other
sinatra-contrib features, use the :require=>false workaround and manually
require the features you need (e.g. require "sinatra/multi_route", require
"sinatra/respond_with"). (Or you can do e.g.
:require=>["sinatra/multi_route", "sinatra/respond_with"] in your Gemfile.)
3. If you need Sinatra::Namespace, consider requiring "sinatra/base"
instead of "sinatra" and modifying your app to run in modular
mode (subclassing Sinatra::Application or Sinatra::Base).
4. If you need Sinatra::Namespace and modular mode isn't an option for
some reason, you just need to restructure your requires so that "sinatra"
and "sinatra/namespace" aren't loaded until you're already within the
context of a Rake task. This basically means that you have to set
:require=>false for both gems in your Gemfile, put all your Sinatra-related
requires in app.rb (or whatever), and don't require app.rb as a part of
your global boot-up routine. Just require it from config.ru,
spec_helper.rb, et al as needed.

Hope that helps a bit.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Tim Uckun
2017-09-28 04:49:29 UTC
Permalink
I have done #4.

I was thinking about the subclassing route but it's going to take a little
bit of work to redo the app. I probably should have started there in the
first place. One thing I have done is to split the routes into different
files so those will have to be wrapped in the class definition they belong
in.

On Thu, Sep 28, 2017 at 2:28 PM, 'Mike Pastore' via sinatrarb <
Post by 'Mike Pastore' via sinatrarb
Post by Tim Uckun
My app is the example :)
That doesn't really illustrate the issue, but I was able to google around
and find an old issue
<https://github.com/sinatra/sinatra-contrib/issues/111> that I think is
the same thing as you're dealing with. Here's a simple Rakefile that
clearly shows the conflict (just run "rake" in the same directory to see
require 'sinatra'
require 'sinatra/namespace'
p method(:namespace).source_location # => ["/Users/mwp/.rbenv/versions/
2.4.2/lib/ruby/gems/2.4.0/gems/sinatra-2.0.0/lib/sinatra/base.rb", 1921]
# I can't do a Rake namespace here!
task(:default) {}
It's a weird issue that I've never run into because I almost always use
modular mode (subclassing Sinatra::Application or Sinatra::Base). In this
mode, you require "sinatra/base", not "sinatra", and Sinatra doesn't set up
the delegation from the top-level context to itself. (In "classic" mode,
Sinatra::Namespace just piggybacks off this mechanism to add its :namespace
method to the list of delegated methods.)
I know you already have a workaround—and there's an around-alias
workaround described in that issue report—but I'd like to offer a few more
1. If you're not using any sinatra-contrib features, just remove it
from your Gemfile.
2. If you don't need Sinatra::Namespace but you're using other
sinatra-contrib features, use the :require=>false workaround and manually
require the features you need (e.g. require "sinatra/multi_route", require
"sinatra/respond_with"). (Or you can do e.g. :require=>["sinatra/multi_route",
"sinatra/respond_with"] in your Gemfile.)
3. If you need Sinatra::Namespace, consider requiring "sinatra/base"
instead of "sinatra" and modifying your app to run in modular
mode (subclassing Sinatra::Application or Sinatra::Base).
4. If you need Sinatra::Namespace and modular mode isn't an option for
some reason, you just need to restructure your requires so that "sinatra"
and "sinatra/namespace" aren't loaded until you're already within the
context of a Rake task. This basically means that you have to set
:require=>false for both gems in your Gemfile, put all your Sinatra-related
requires in app.rb (or whatever), and don't require app.rb as a part of
your global boot-up routine. Just require it from config.ru,
spec_helper.rb, et al as needed.
Hope that helps a bit.
--
You received this message because you are subscribed to the Google Groups
"sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
'Mike Pastore' via sinatrarb
2017-09-25 17:30:37 UTC
Permalink
Post by c***@gmail.com
If you care a lot about efficiency, you might want to try Hobby
<https://github.com/ch1c0t/hobby>. According to this benchmark
<https://github.com/luislavena/bench-micro#have-some-numbers-around>,
Hobby is a lot faster than Sinatra.
This is a Sinatra discussion group. Please don't plug Sinatra alternatives
here. I'm sure Hobby is great, but this is not the place to discuss it.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
'Mike Pastore' via sinatrarb
2017-09-25 17:52:32 UTC
Permalink
Post by Tim Uckun
I am writing an API in sinatra. It will be a pure JSON api so I need to
parse the body as JSON and I am wondering whether it's more efficient to do
that with a middleware or as a before hook?
I have not benchmarked it, but my intuition tells me that doing something
locally in your current app will always be faster than doing the same
operation in a newly-introduced middleware layer. That being said, I don't
think the performance delta would be significant. Since you're struggling
to get started, you might consider worrying less about efficiency, and more
about getting it up and running.

Also a question about the general setup. I will have public paths and
Post by Tim Uckun
private paths and I will be using JWT. One approach is to create a
namespace for the private and as a before or use setting make sure the JWT
exists and is valid. Another approach would be to create two apps one for
the private and one for the public and mount them on different paths. Is
one way more efficient than the other?
A namespace uses Sinatra's internal routing. With a separate path prefix
you could use an external routing library like Rack::URLMap. So you're
really asking which is faster.

Again, I haven't benchmarked this exact scenario, but: Rack::URLMap was
faster, hands down, prior to Sinatra 2.0. With Mustermann 1.0, I think
Sinatra 2.0's routing performance is approaching parity with Rack::URLMap.
And again, I think your worry about efficiency and performance is premature
at this stage in the game.

Finally. How about I group similar functionality into a separate app and
Post by Tim Uckun
have many apps each of which inherits from a base app but is mounted on
different paths. Does Sinatra initialize all the classes on every request
or only initialize them when the mounted path is hit?
A Sinatra app will initialize new class(es) when it is called, so when the
mounted path is hit.
--
You received this message because you are subscribed to the Google Groups "sinatrarb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sinatrarb+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...