Project

watts

0.01
No release in over 3 years
Low commit activity in last 3 years
Resource-oriented, Rack-based, minimalist web framework.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 0
 Project Readme
# Watts

## Intro

Watts is a minimalist, Rack-based, resource-oriented web framework.  It
has fewer than 400 lines of code (including comments), no dependencies
(besides Rack), and only does one thing: it maps resources.

See doc/LICENSE for the license.  See doc/examples if you're impatient.

## Goals

Dead-simple web development.  I don't want a framework to take up so
much of my brain that there's no space left for my application.

## Resource Orientation

If you think of resources as first-class objects, and then think of HTTP
methods as operations on those objects, then this should probably make
sense.

Most of the web frameworks I have seen seem to be HTTP-method-oriented
rather than resource-oriented.  It seems odd to me (not to mention
repetitive) that you would type "A GET on /foo does this, a POST on /foo
does that, ..." rather than "There's a resource at /foo.  That
resource's GET does this, and its POST does that, ...".

And because the second one made more sense to me, that's how I wrote
Watts.  Let me clarify if that was a bit vague, by showing how a Watts
app comes into being:
* You make a resource by sub-classing `Watts::Resource`.  
* On this resource, you define some basic operations, in terms of HTTP
methods.
* You create an app by sub-classing `Watts::App`.
* You use the resource() method to tell Watts the path under which the
resource can be found.

There are a few easy-to-read examples in doc/examples.

## Pattern-matching

That resource() method mentioned above?  It does some pattern-matching
on the different components of the path.  They all arrive as strings, of
course.  The priority for matches is that Watts will attempt to match a
string literally if possible.  Next it tries to match any regex patterns
that have been specified, and failing that, symbols are used as a
catch-all.  Here are a few patterns and the things they match:
* '' matches "/"
* 'foo' matches "/foo".
* 'foo/bar' matches "/foo/bar".
* [] matches "/".
* ['foo'] matches "/foo".
* ['foo', 'bar'] matches "/foo/bar".
* ['foo', /^[0-9]+$/] matches "/foo/", followed by a string of digits.
The matching part of the path will be passed as an argument to the
method on the resource when it is called.
* ['foo', :arg] matches "/foo/" followed by anything.  Like with the
regex, the argument is passed in.  The symbol's actual value doesn't
really matter to Watts; it is intended for documentation.

See doc/examples/matching.ru.

## What methods return:

When you define an HTTP method on a `Watts::Resource`, the best thing
to return is an array in the format Rack expects for responses, namely:

 [status_code, {headers}, [body, ...]]

For the sake of convenience, Watts will attempt to do the right thing
if you return a bare string (in which case, it is treated as `text/plain`).
If the return value is a `Rack::Response`, then Watts will use that.  If you
call `Watts::Resource#response`, a `Rack::Response` will be created if it
does not exist, and that response will be used if the return value is nil.

The Rack API has changed a handful of times recently, so see SPEC.rdoc in
the Rack repo or use ri(1) or on the web:
https://github.com/rack/rack/blob/main/SPEC.rdoc#label-The+Response .

Note also that, although HTTP headers are case-insensitive,
`Rack::Lint` has started throwing errors if you use the canonical case
(e.g., "User-Agent", "Content-Type") rather than all lower-case (e.g.,
"user-agent", "content-type").  The canonical case for HTTP headers is
used in the RFCs, in nearly every web server and user agent since the
1990s, as well as all of the documentation, including the IANA's
header registry:  http://www.iana.org/assignments/message-headers .
As Watts is designed to work with Rack, though, Watts now emits only
lower-case header names in the few places where it does emit headers.

`Rack::Lint` is of dubious utility and can be disabled without consequence.

See doc/examples/return.ru.

* A string, in which case, 

## REST, RFC 2616, TL;DR

There's a lot of talk on the internets about what exactly REST is, why it's
important, why we're doing it wrong, content-negotiation, discoverability,
avoiding out-of-band communication, and all of that stuff.  Watts makes it a
little easier to comply with the spec than Rails or Sinatra if you know what the
spec says, but it doesn't force it on you.  (You should definitely care, but
Watts won't make you.)

## Design

Lots of web frameworks move very quickly, have a large number of features, a
large number of bugs resulting from the large number of features, and an onerous
upgrade process when updating to a new version.  Watts has a much more
strict policy:  do not add a feature unless it is obviously correct.

Except for the earliest versions, every new feature that made it into Watts has
been implemented in two or three Watts applications, and looks very different
than it would look if it had been implemented based on speculation.  (I've been
hacking for a long time; this may seem obvious to older hackers, but you have to
build something a few times before you understand it well enough to put it into
a framework.)

If you feel that Watts sorely misses some features, the codebase is very small,
and as a result very amenable to extension.

## Bugs

I'm sure they're present.  You can email me about them, or ping me on
GitHub, or send a patch.

There do not seem to be too many.  There is a test suite.

## About the Name

I named it after a character in a video game that I liked as a kid (and still
like).  It's also the name of a city not far from where I live.

Also:  joules per second.

The Watts in question:

░░░█░░██▒█░░█░░ ███░██░░▓░██░██
░░█▒██▓█▒▓██▒█░ ██░▓░░▒░▓▒░░▓░█
░█▒██▓▓█▒▓▓██▒█ █░▓░░▒▒░▓▒▒░░▓░
░█▒▒▒███▒███▒▒█ █░▓▓▓░░░▓░░░▓▓░
░░█▒█▒▒▒▒▒▒█▒█░ ██░▓░▓▓▓▓▓▓░▓░█
░░░█▒██████▒█░░ ███░▓░░░░░░▓░██
░░█▒██▒██▒██▒█░ ██░▓░░▓░░▓░░▓░█
░░░███▒██▒███░░ ███░░░▓░░▓░░░██
░█▒▓█▒████▒█▓█░ █░▓▒░▓░░░░▓░▒░█
█▒▒▓▓█▒▒▒▒█▓██░ ░▓▓▒▒░▓▓▓▓░▒░░█
█▒▒█▓██▒▒█▓█▒▒█ ░▓▓░▒░░▓▓░▒░▓▓░
█▒██▓█▓██▓▓█▒▒█ ░▓░░▒░▒░░▒▒░▓▓░
░█░██▒████████░ █░█░░▓░░░░░░░░█
░░░█▓▓▓▓█▓▓█░░░ ███░▒▒▒▒░▒▒░███
░░░░█▓▓▓███░░░░ ████░▒▒▒░░░████
░░████████████░ ██░░░░░░░░░░░░█


## Author

Pete Elmore.  Feel free to email me using pete at debu dot gs.  I'm on
GitHub at http://github.com/pete .  Also there's http://debu.gs/ , which
runs Watts.

### Acknowledgements

The commits coming just from me is a bit misleading!  Suggestions and tweaks
have been provided by friends and coworkers:

* John Dewey ( http://bitbucket.org/retr0h )
* Jim Radford ( http://github.com/radford )
* Johnathon Britz ( http://github.com/johnathonbritz )
* Justin George ( http://github.com/jaggederest )

And, as with Hoshi ( http://github.com/pete/hoshi ), I think I'll continue the
tradition of crediting the music I was blasting while writing out the first
draft:  Softball and Dance☆Man.