lib/satz.rb in satz-0.0.1 vs lib/satz.rb in satz-0.0.2
- old
+ new
@@ -20,27 +20,86 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
require "syro"
require "json"
+require "base64"
class Satz
+
+ # The JSON module from stdlib provides a safe way of loading data
+ # with the `parse` method, but the most widespread API for encoding
+ # and decoding data is with the `load` and `dump` methods, which in
+ # the case of JSON are unsafe. This module wraps the JSON constant
+ # from stdlib in order to expose a safe version of `load`. As the
+ # serializer is configurable, the user is expected to provide
+ # objects that respond safely to those methods.
+ module Serializer
+ def self.load(value)
+ JSON.load(value, nil, create_additions: false)
+ end
+
+ def self.dump(value)
+ JSON.dump(value)
+ end
+ end
+
+ @@serializer = Serializer
+
+ def self.serializer
+ @@serializer
+ end
+
+ # Modify the serializer to be used for all Satz applications.
+ # The serializer object must reply to `load(arg)` and `dump(arg)`.
+ def self.serializer=(value)
+ @@serializer = value
+ end
+
class Deck < Syro::Deck
+ HTTP_AUTHORIZATION = "HTTP_AUTHORIZATION".freeze
- # Respond by default with JSON.
+ # Checks the Basic Auth headers and yields
+ # user and pass if credentials are provided.
+ # Returns nil if there are no credentials or
+ # if the block returns false or nil.
+ #
+ # Usage:
+ #
+ # @user = auth do |user, pass|
+ # User.authenticate(user, pass)
+ # end
+ #
+ # on @user.nil? do
+ # res.status = 401
+ # reply(error: "Unauthorized")
+ # end
+ #
+ def auth
+ http_auth = env.fetch(HTTP_AUTHORIZATION) do
+ return nil
+ end
+
+ cred = http_auth.split(" ")[1]
+ user, pass = Base64.decode64(cred).split(":")
+
+ yield(user, pass) || nil
+ end
+
+ # Respond by default with JSON. The default charset
+ # for "application/json" is UTF-8.
def default_headers
{ "Content-Type" => "application/json" }
end
# Read JSON data from the POST request.
def read
- body = req.body.read
- body && JSON.parse(body)
+ Satz.serializer.load(req.body.read)
end
# Write JSON data to the response.
def reply(data)
- res.write(JSON.dump(data))
+ res.write(Satz.serializer.dump(data))
end
end
def self.define(&code)
Syro.new(Deck, &code)