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)