

The Revel Web Framework for Go - staunch
http://robfig.github.io/revel/

======
robfig
Author here, to provide a bit of context.

Initially, this was just a fun project to see if I could replicate the magical
Play! 1.x experience in much-less-magical Go. (Spoiler alert: yes)

Along the way, I started thinking more seriously about the right way to put
together web applications and did more research into how Rails and Play 2.x
are structured. Although Play 1.x was amazing, I think that there are some
obvious areas for improvement -- the design of 2.x seems to be much better
(although I'm personally allergic to Scala).

So the goal posts have shifted. I see this ending up as two things,
conceptually:

1\. A framework like Rack, in the sense of being a straightforward interface
for writing and composing aspects of web applications. (Revel calls them
Filters). Some components (Router, TemplateLoader) have defined interfaces so
that other components can use them (but most components do not).

2\. A default stack of components that work well together out of the box. No
size fits all, but the two concrete use cases I have in mind are writing large
business applications and REST APIs.

The goal is that the revel package shrinks to encompass just the "Rack"-like
framework, and the revel command line tool can generate a project with the
default components set up.

This appears to be achievable; it just requires a bit of work, and I have been
quite busy with the day job. More people are using it than I anticipated, so I
would like to complete the core design so that it can be properly released.

=====

APPENDIX (EDIT)

FAQ: "Why not just use vanilla Go, since it already provides X, Y, and Z":

Go certainly ships with more components in place than any language I'm aware
of, but I still think there is a lot of value in providing a default stack of
stuff with a fixed, conventional app organization in terms of lowering the
cognitive load bar.

If you are making a single endpoint and are a Golang whiz, then Revel is not
for you. But for many things it's about the concepts more than the code. For
example, the code dealing with the flash cookie is not many lines; most of the
value there is having it integrated, documented, and exampled. Empirically, I
believe that Rails unlocked a latent desire for web development by lower the
bar -- I think Revel can lower the bar for web development with Go in the same
way.

Lastly, there is something to be said for having an integrated web framework
instead of a franken-app composed of various libraries. Take parsing
parameters as an example. With a library, how can you get close to the ease
that Revel provides? [1]

You may think it's dumb, but I find it so much nicer to simply accept
parameters as the type that I want them in, and let Revel figure it out
instead of me having to figure out the right strconv / etc function to call.
The goal is for Revel to take care of all that stuff and let me focus on the
higher level stuff.

[1]
[http://robfig.github.io/revel/manual/binding.html#action_arg...](http://robfig.github.io/revel/manual/binding.html#action_arguments)

~~~
johnx123-up
Just a feedback... though we like Revel, it could have been a clone of Rails
or Scooter (Java) or CakePHP -- with strict coding standards than Play 1/2
that looks more of a kludge especially when you come from Rails.

~~~
garysweaver
The first version of anything worthwhile is typically an experiment. I'm
excited about the prospect of a great way to write Go apps in the future that
is better than what we have now. One of the best ways to kill a project is by
trying to be something else.

------
bhauer
Apparently today is the day to post links to alternative web frameworks. Right
on.

Incidentally, Revel achieves an exceptional framework overhead rating in our
tests. In our i7 Fortunes test [1], Revel performs at 96.5% of its platform,
Go. (See rightmost tab on the results panel.)

[1]
[http://www.techempower.com/benchmarks/#section=data-r6&hw=i7...](http://www.techempower.com/benchmarks/#section=data-r6&hw=i7&test=fortune)

~~~
biot
Wouldn't this be better described as Framework Efficiency? The framework
operates at 96.5% efficiency, not with 96.5% overhead. At 96.5% efficiency,
the overhead is 3.6%.

~~~
bhauer
Yes. However, I want to expressly avoid the word "efficiency" because it is
our intent to eventually capture some metric(s) related to developer
efficiency (e.g., lines of code and so on). I don't want the word efficiency
to then be ambiguous, at least within our results site.

I struggled for a while with various alternatives, but ultimately went with
"overhead" even though, as you point out, a higher number is better. I'm open
to other suggestions, but for the time being, I'd like to avoid efficiency.

Edit: The trouble with inverting the metric ("lower is better") is that in
some cases, a framework achieves superior performance than its underlying
platform due to custom components or test implementation particulars. See for
instance the multiple query test in which presently Revel exceeds Go (I know
at least one Go SME is researching why this is).

[http://www.techempower.com/benchmarks/#section=data-r6&hw=i7...](http://www.techempower.com/benchmarks/#section=data-r6&hw=i7&test=query)

~~~
lstamour
As others have mentioned, it was really quite confusing to see "higher is
better" and then "lower is better" in the same set of graphs. Stick with one
convention. It works. :)

~~~
bhauer
Interesting. That is actually an argument to leave the overhead chart as-is
(possibly renamed) but change the latency chart to a "higher is better" chart
in some way. I don't disagree that a single convention would be preferable,
but it would be unusual to represent latency in a higher-is-better fashion.

Thanks all for the input here!

------
SkyMarshal
In this day and age, why don't most web frameworks consider security features
to be a selling point? Revel, for example, doesn't mention it once on their
front page, and only 5 results in their Google Group when searching for
"security" [1].

Is it just the case that speed - both of development and request/response
performance - sells, and security is considered a solved problem, or something
that should be implemented at the project level rather than framework level?

[1]: [https://groups.google.com/forum/#!searchin/revel-
framework/s...](https://groups.google.com/forum/#!searchin/revel-
framework/security)

~~~
tptacek
Which security features are you thinking of? The only unmitigated successes I
can think of are pretty standard and hard to market --- default XSS string
tainting/quoting and CSRF protection.

~~~
SkyMarshal
Ideally it would be nice to see a Security page with anything and everything
related to security:

\- Security reporting SOP

\- CVE-IDs (not applicable w/ new projects obviously)

\- Links to documenation on methods of Authentication, Authorization, Access
Control, etc

\- Details on any built-in countermeasures to applicable OWASP Top 10, and/or
example implementation code for security-per-project frameworks

Some partial examples, all easy to find a click or two away from the
framework's home page:

[http://www.djangobook.com/en/2.0/chapter20.html](http://www.djangobook.com/en/2.0/chapter20.html)

[http://www.yiiframework.com/doc/guide/1.1/en/topics.security](http://www.yiiframework.com/doc/guide/1.1/en/topics.security)
(docs page, but linked directly from Features list page)

[http://www.yiiframework.com/doc/guide/1.1/en/topics.auth](http://www.yiiframework.com/doc/guide/1.1/en/topics.auth)
(docs page, but linked directly from Features list page)

[http://symfony.com/doc/current/contributing/code/security.ht...](http://symfony.com/doc/current/contributing/code/security.html)
(more on their vulnerability reporting process, but nice to know their SOP)

[http://seventhings.liftweb.net/security](http://seventhings.liftweb.net/security)

[http://cakephp.org/](http://cakephp.org/) (not great but at least they pay
some lip service to it on the home page, implying more details can be found
digging around in the docs/source)

[http://www.springsource.org/features/security](http://www.springsource.org/features/security)
(also not great but again, implying it can be found with some digging)

This stuff may be SOP for mature frameworks, but would be nice to see it on
new ones too.

------
tptacek
What kills me about rich web frameworks for Golang is that the ORM problem for
Golang is still open; there isn't a "mainstream" best ORM to use, and so
frameworks don't have tight integration with storage; there's no "model" layer
to work with.

If a framework is going to solve approximately the same set of problems for me
as Sinatra, I'm not sure that's a big enough win over what Golang already
ships with.

~~~
redbad
An ORM is absolutely not a requirement of a functional web framework. Many
people, myself included, consider ORMs harmful.

~~~
EliAndrewC
I'm aware that many people don't use ORMs and feel they cause more problems
than they solve. However, I'm struggling to think of a popular web framework
in any language that doesn't include or suggest a specific ORM.

So out of curiosity, when you do web development, do you use an ORM-less
framework, or do you simply not use the ORM that's included/recommended?

~~~
wheaties
Unfiltered of Scalable does not thankfully ship with one.

Flask of Python does not ship with one.

Want more?

------
stormbrew
It drives me nuts that new frameworks announce that they've stuffed all your
app's routing into one file like Rails does as if that's a feature. I'm not
sure I've ever seen a large rails app where the routing doesn't become an
absolute rats nest.

~~~
tyre
Rails allows you to split them up:

    
    
      MyApp::Application.routes.draw do
        load 'config/routes/more_routes.rb'
      end
    

I agree that routes files have a tendency to turn nightmarish (combination of
low rate of change once set and you almost never have a reason to read them.)
At the same time, if you're routes are getting intimidating it may be time to
break out application into separate concerns.

~~~
stormbrew
> At the same time, if you're routes are getting intimidating it may be time
> to break out application into separate concerns.

I agree. But at the same time, not a lot of frameworks out there really help
you make your app more modular. Rails certainly didn't until relatively
recently (late rails 2, big improvements in rails 3).

------
mailslot
Revel worked really well for a project of mine with MongoDB... a DB that
doesn't really play well with traditional ORMs. The idiomatic Marshall &
Unmarshall features of the language carry over to the Mgo driver. Basically,
Go already has an ORM, if you use it this way. I can use the same definition
to consume XML into a native struct, manipulate, and then marshal a JSON
response to the browser and a BSON value to the DB.

------
latch
One of the places Go excels is at sharing memory between goroutines. Most web
apps are built so that each request is independent of all other requests.
Which isn't to say Go's a bad fit for all web apps, I just don't think most
will gain anything from it.

We've used it for just another web app, and haven't gotten any value of out
it...except learning Go. Then we deployed it as a piece of infrastructure,
something that would have been hard to write in Node or Ruby, and it's been a
real win.

~~~
robfig
Here's a big one: you can write your routines in a completely synchronous,
blocking style. The Go runtime automatically async-izes that for you.

This is like getting the benefit of an evented system without paying the cost
of structuring your code with callbacks (or other workaround).

------
AYBABTME
Is there any news here? Revel is not new.

Don't get me wrong, I'm always excited about Go tech but Revel has been around
for a while and I fail to see why today, specifically, it is on HN's main
page.

~~~
marknutter
I had never heard of it until now. That's why.

------
paulsutter
Could someone explain what problem this solves? Go already has http,
templates, and (duh) goroutines. What is Revel adding?

Sure, PHP programmers are accustomed to having their syntax errors detected by
surprise at runtime. But aren't we choosing Go because it can detect those
errors before we've deployed? [1]

In Java it may feel natural to take a simple task like dispatching a URL
("Routing"), and turn it into an elaborate overabstracted object architecture.
But aren't we choosing Go to escape that nonsense? [2]

[1]
[http://robfig.github.io/revel/img/helpfulerror.png](http://robfig.github.io/revel/img/helpfulerror.png)

[2]
[http://robfig.github.io/revel/manual/concepts.html](http://robfig.github.io/revel/manual/concepts.html)

Am I missing something?

EDIT: I've seen lots of Go applications, and none of them have spent
8432579842375 hours developing scaffolding. Actually, they saved time not
having to spray their logic across a zillion source files.

~~~
dualogy
It says right on the OP-linked page:

 _Revel provides routing, parameter parsing, validation, session /flash,
templating, caching, job running, a testing framework, and even
internationalization._

~~~
throwit1979
Preface: I absolutely love Revel, and I hope to put something built on it into
production very soon.

That said, I'd be hesitant to bring up Revel's session as a positive. It
shoves _everything_ into a cookie instead of using the cookie token as a key
to a serverside data store. Not only are you limited to 4k of session-local
storage, but you're sending the entire payload across the wire for every
single request. This is absolutely stupid and needs to change. I'm sure Rob is
boxed in by limited time, and this is not intended for production use yet, but
holy god, it's by far the worst thing about the framework.

~~~
akmiller
Well, how hard is it to just use their session store to store a guid of some
type and use that key to store session data in redis or some other storage?

~~~
throwit1979
That's what I do, and it's easy enough, but that's not the point. Revel is
trying to be a comprehensive "ready to go" framework - and as such, it has all
these other features fairly well covered, but it's falling down, relatively
speaking, in this one.

------
zemo
>A Controller is any type that embeds _revel.Controller (directly or
indirectly)._ revel.Controller must be embedded as the first type in your
struct

(－‸ლ)

~~~
coldtea
You'd rather implement the interface methods yourself?

Or you think it's possible to have some random type serve as a controller
without the necessary interface by magic?

~~~
zemo
if you anonymously embed a structure, the containing structure gets its
methods. If the contained structure satisfies an interface, then the
containing structure does as well.

Attempting to create inheritance features is ignoring the nature of Go's type
system; it's the opposite of idiomatic.

~~~
robfig
Are you suggesting that the design would be better if instead Controller was
an interface?

I agree that it seems enticing, for exactly the reason you mention. However, I
think the interface solution would require setters and getters for every
single field, which seems much worse to me.

~~~
zemo
>I think the interface solution would require setters and getters for every
single field

not if you use struct tags. e.g.,

    
    
        type MyController struct {
            Id int `revel.q="id,required=true,min=0,max=200"`
        }
    

or something like that. Then the framework just fills the controllers field on
an incoming request, based on what it finds in the struct tags. Then you have
an interface that allows you to override that behavior, similar to how the
json package will use the methods defined in `json.Unmarshaler` if you define
them, but will fall back to controlling things by itself with reflection if
you don't.

