roy 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/lib/roy/after.rb +26 -0
- data/lib/roy/base.rb +8 -0
- data/lib/roy/basic_auth.rb +68 -12
- data/lib/roy/before.rb +29 -0
- data/lib/roy/context.rb +30 -1
- data/lib/roy/halt.rb +31 -4
- data/lib/roy/render.rb +88 -13
- data/lib/roy/version.rb +3 -1
- data/test/plugins/basic_auth_test.rb +1 -1
- metadata +11 -11
data/Gemfile.lock
CHANGED
data/LICENSE
CHANGED
data/lib/roy/after.rb
CHANGED
@@ -1,4 +1,30 @@
|
|
1
1
|
module Roy
|
2
|
+
# This module allows you to modify the response before it is sent to the
|
3
|
+
# client. It does this by overriding the {Roy#call} method.
|
4
|
+
#
|
5
|
+
# == Configuration:
|
6
|
+
# roy.conf.after::
|
7
|
+
# A proc object that will be called with the response as argument.
|
8
|
+
# Defaults to identity if not set.
|
9
|
+
#
|
10
|
+
# @example Forcing a custom content-type
|
11
|
+
#
|
12
|
+
# class SetContentType
|
13
|
+
# include Roy
|
14
|
+
#
|
15
|
+
# roy use: [:after],
|
16
|
+
# after: ->(resp) { resp.headers['Content-Type'] = 'text/x-foo' }
|
17
|
+
#
|
18
|
+
# def get(_)
|
19
|
+
# "Hello, world\n"
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @example Demo
|
24
|
+
#
|
25
|
+
# $ curl -i localhost:9292
|
26
|
+
# HTTP/1.1 200 OK
|
27
|
+
# Content-Type: text/x-foo
|
2
28
|
module After
|
3
29
|
def call(env)
|
4
30
|
status, header, body = super
|
data/lib/roy/base.rb
CHANGED
@@ -9,17 +9,23 @@ require 'ostruct'
|
|
9
9
|
require 'roy/version'
|
10
10
|
require 'roy/context'
|
11
11
|
|
12
|
+
# This is the main module that applications should include.
|
12
13
|
module Roy
|
14
|
+
|
15
|
+
# Default options.
|
13
16
|
Defaults = {allow: [:get], prefix: :'', use: [:halt]}
|
14
17
|
|
18
|
+
# Extend the class with the ClassMethods module.
|
15
19
|
def self.included(base)
|
16
20
|
base.send(:extend, ClassMethods)
|
17
21
|
end
|
18
22
|
|
23
|
+
# Returns the application context or initialize it
|
19
24
|
def roy
|
20
25
|
@roy ||= Context.new(self)
|
21
26
|
end
|
22
27
|
|
28
|
+
# A Rack-compliant #call method.
|
23
29
|
def call(env)
|
24
30
|
roy.prepare!(env)
|
25
31
|
|
@@ -41,6 +47,7 @@ module Roy
|
|
41
47
|
module ClassMethods
|
42
48
|
attr_reader :conf
|
43
49
|
|
50
|
+
# Setup default configuration for the application.
|
44
51
|
def self.extended(base)
|
45
52
|
base.instance_eval do
|
46
53
|
@conf ||= OpenStruct.new
|
@@ -48,6 +55,7 @@ module Roy
|
|
48
55
|
end
|
49
56
|
end
|
50
57
|
|
58
|
+
# Set options for the application
|
51
59
|
def roy(options={})
|
52
60
|
options.each do |key,value|
|
53
61
|
case key
|
data/lib/roy/basic_auth.rb
CHANGED
@@ -1,20 +1,76 @@
|
|
1
1
|
module Roy
|
2
|
+
# This module provides helpers for using the HTTP basic authentication system.
|
3
|
+
#
|
4
|
+
# == Configuration:
|
5
|
+
# roy.conf.auth [:realm]::
|
6
|
+
# The authentication realm to use.
|
7
|
+
# roy.conf.auth [:logic]::
|
8
|
+
# A proc that checks if an user is authorized. See #authorized? in
|
9
|
+
# InstanceMethods.
|
10
|
+
#
|
11
|
+
# @example Simple auth example
|
12
|
+
#
|
13
|
+
# class AuthApp
|
14
|
+
# include Roy
|
15
|
+
# roy use: [:basic_auth],
|
16
|
+
# auth: {
|
17
|
+
# realm: "My Realm",
|
18
|
+
# logic: ->(_, u, p) { %w(admin foobar) == [u, p] }
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# def get(_)
|
22
|
+
# roy.protected!
|
23
|
+
# "Protected zone"
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# @example Using user data
|
28
|
+
#
|
29
|
+
# class AuthUserDataApp
|
30
|
+
# include Roy
|
31
|
+
# roy use: [:basic_auth],
|
32
|
+
# auth: {
|
33
|
+
# realm: "My Realm",
|
34
|
+
# logic: ->(override, u, p) {
|
35
|
+
# override || (%w(admin foobar) == [u, p])
|
36
|
+
# }
|
37
|
+
# }
|
38
|
+
#
|
39
|
+
# def get(path)
|
40
|
+
# roy.protected!(path =~ /private/)
|
41
|
+
# "Protected if path contains private"
|
42
|
+
# end
|
43
|
+
# end
|
2
44
|
module BasicAuth
|
3
|
-
def
|
4
|
-
|
5
|
-
realm = roy.conf.auth && roy.conf.auth[:realm] || 'Realm'
|
6
|
-
roy.response['WWW-Authenticate'] = %(Basic realm="#{realm}")
|
7
|
-
roy.halt 401
|
8
|
-
end
|
45
|
+
def self.setup(roy)
|
46
|
+
roy.send(:extend, InstanceMethods)
|
9
47
|
end
|
10
48
|
|
11
|
-
|
12
|
-
|
49
|
+
module InstanceMethods
|
50
|
+
|
51
|
+
# Protect all subsequent code using HTTP Basic Authentication.
|
52
|
+
#
|
53
|
+
# @param data user data to pass to #authorized?
|
54
|
+
def protected!(data=nil)
|
55
|
+
unless authorized?(data)
|
56
|
+
realm = conf.auth && conf.auth[:realm] || 'Realm'
|
57
|
+
response['WWW-Authenticate'] = %(Basic realm="#{realm}")
|
58
|
+
halt 401
|
59
|
+
end
|
60
|
+
end
|
13
61
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
62
|
+
# Runs the authentication logic against the user and passord given in the
|
63
|
+
# request, using custom additional data.
|
64
|
+
#
|
65
|
+
# @param data user data to pass to the authentication logic
|
66
|
+
def authorized?(data=nil)
|
67
|
+
auth = Rack::Auth::Basic::Request.new(request.env)
|
68
|
+
|
69
|
+
auth.provided? && auth.basic? && auth.credentials &&
|
70
|
+
(conf.auth[:logic] || ->(data, u, p) {
|
71
|
+
%w(admin password) == [u, p]
|
72
|
+
}).(data, *auth.credentials)
|
73
|
+
end
|
18
74
|
end
|
19
75
|
end
|
20
76
|
end
|
data/lib/roy/before.rb
CHANGED
@@ -1,4 +1,33 @@
|
|
1
1
|
module Roy
|
2
|
+
# This module allows you to modify the environment before it is handled by the
|
3
|
+
# application. It does this by overriding the {Roy#call} method.
|
4
|
+
#
|
5
|
+
# == Configuration:
|
6
|
+
# roy.conf.before::
|
7
|
+
# A proc object that will be called with the environment as argument.
|
8
|
+
# Defaults to identity if not set.
|
9
|
+
#
|
10
|
+
# @example Forcing a method
|
11
|
+
#
|
12
|
+
# class AlwaysGet
|
13
|
+
# include Roy
|
14
|
+
#
|
15
|
+
# roy allow: [:put, :post], use: [:before],
|
16
|
+
# before: ->(env) { env['REQUEST_METHOD'] = 'GET' }
|
17
|
+
#
|
18
|
+
# def get(_)
|
19
|
+
# "Hello, world\n"
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @example Demo
|
24
|
+
#
|
25
|
+
# $ curl -i localhost:9292
|
26
|
+
# HTTP/1.1 200 OK
|
27
|
+
# $ curl -X POST -i localhost:9292
|
28
|
+
# HTTP/1.1 200 OK
|
29
|
+
# $ curl -X PUT -i localhost:9292
|
30
|
+
# HTTP/1.1 200 OK
|
2
31
|
module Before
|
3
32
|
def call(env)
|
4
33
|
(roy.conf.before || lambda {|x| x }).(env)
|
data/lib/roy/context.rb
CHANGED
@@ -1,7 +1,33 @@
|
|
1
1
|
module Roy
|
2
|
+
# Application context for Roy applications.
|
3
|
+
#
|
4
|
+
# Everything must be namespaced in this context to avoid any clashes and to
|
5
|
+
# make the code cleaner.
|
2
6
|
class Context
|
3
|
-
|
7
|
+
# Returns the current application
|
8
|
+
attr_reader :app
|
4
9
|
|
10
|
+
# Returns the application's configuration
|
11
|
+
attr_reader :conf
|
12
|
+
|
13
|
+
# Returns the environment passed to #call
|
14
|
+
attr_reader :env
|
15
|
+
|
16
|
+
# Returns the current request
|
17
|
+
attr_reader :request
|
18
|
+
|
19
|
+
# Returns the current response
|
20
|
+
attr_reader :response
|
21
|
+
|
22
|
+
# Returns the current response's headers
|
23
|
+
attr_reader :headers
|
24
|
+
|
25
|
+
# Returns the current request's params
|
26
|
+
attr_reader :params
|
27
|
+
|
28
|
+
# Creates a new Context object.
|
29
|
+
#
|
30
|
+
# @param app the context's application
|
5
31
|
def initialize(app)
|
6
32
|
@app = app
|
7
33
|
@conf = app.class.conf
|
@@ -11,6 +37,9 @@ module Roy
|
|
11
37
|
end
|
12
38
|
end
|
13
39
|
|
40
|
+
# Initializes the attributes based on an environment.
|
41
|
+
#
|
42
|
+
# @param env the environment to use
|
14
43
|
def prepare!(env)
|
15
44
|
@env = env
|
16
45
|
@request = Rack::Request.new(env)
|
data/lib/roy/halt.rb
CHANGED
@@ -1,11 +1,38 @@
|
|
1
1
|
module Roy
|
2
|
+
# This module adds a +halt+ method to the application context that allows you
|
3
|
+
# to break during a handler and immediately return a status code and a body.
|
4
|
+
#
|
5
|
+
# Included by default.
|
6
|
+
#
|
7
|
+
# @example A Not Found application
|
8
|
+
#
|
9
|
+
# class NotFoundApp
|
10
|
+
# include Roy
|
11
|
+
#
|
12
|
+
# def get(_)
|
13
|
+
# halt 404
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# @example Test
|
18
|
+
#
|
19
|
+
# $ curl -i localhost:9292
|
20
|
+
# HTTP/1.1 404 Not Found
|
2
21
|
module Halt
|
3
22
|
|
4
23
|
def self.setup(roy)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
24
|
+
roy.send(:extend, InstanceMethods)
|
25
|
+
end
|
26
|
+
|
27
|
+
module InstanceMethods
|
28
|
+
# Break from the current +catch(:halt)+ block
|
29
|
+
#
|
30
|
+
# @param [Integer] code the response status code.
|
31
|
+
# @param [String] message the response body.
|
32
|
+
# @return [Integer, String] the status and the given message or a default
|
33
|
+
# one.
|
34
|
+
def halt(code, message=nil)
|
35
|
+
throw :halt, [code, message || Rack::Utils::HTTP_STATUS_CODES[code]]
|
9
36
|
end
|
10
37
|
end
|
11
38
|
|
data/lib/roy/render.rb
CHANGED
@@ -1,24 +1,99 @@
|
|
1
1
|
require 'tilt'
|
2
2
|
|
3
3
|
module Roy
|
4
|
+
# A simple template rendering mechanism based on Tilt.
|
5
|
+
#
|
6
|
+
# == Configuration:
|
7
|
+
# roy.conf.render::
|
8
|
+
# A hash of options to pass to Tilt.
|
9
|
+
# roy.conf.views::
|
10
|
+
# The directory where views are kept. Defaults to +views/+
|
11
|
+
#
|
12
|
+
# @example Using <tt>roy.render</tt>
|
13
|
+
#
|
14
|
+
# class ErbApp
|
15
|
+
# include Roy
|
16
|
+
#
|
17
|
+
# roy use: [:render]
|
18
|
+
#
|
19
|
+
# def get(path)
|
20
|
+
# case path
|
21
|
+
# when /\/hello/
|
22
|
+
# roy.render :erb, "Hello, <%= roy.params[:p] || \"world\" %>!\n"
|
23
|
+
# else
|
24
|
+
# roy.render :erb, :index
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @example Test
|
30
|
+
#
|
31
|
+
# $ cat views/index.erb
|
32
|
+
# Let me <a href="/hello">greet</a> you.
|
33
|
+
# $ curl -i localhost:9292
|
34
|
+
# Let me <a href="/hello">greet</a> you.
|
35
|
+
# $ curl -i localhost:9292/hello?p=blah
|
36
|
+
# Hello, blah!
|
37
|
+
#
|
38
|
+
# @example Haml renderer with partials support
|
39
|
+
#
|
40
|
+
# module HamlRenderWithPartial
|
41
|
+
# def self.setup(roy)
|
42
|
+
# roy.send(:extend, InstanceMethods)
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# module InstanceMethods
|
46
|
+
# def render(tpl_or_string, params={})
|
47
|
+
# case layout = params.delete(:layout)
|
48
|
+
# when false
|
49
|
+
# super(:haml, tpl_or_string, params)
|
50
|
+
# else
|
51
|
+
# super(:haml, :layout, params do
|
52
|
+
# super(:haml, tpl_or_string, params)
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
# end
|
4
58
|
module Render
|
5
59
|
|
6
60
|
def self.setup(roy)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
when Symbol
|
12
|
-
file = [view_or_string.to_s, engine].map(&:to_s).join('.')
|
13
|
-
dir = conf.views || 'views'
|
14
|
-
Tilt.new(File.join(dir, file), nil, options)
|
15
|
-
else
|
16
|
-
Tilt[engine].new(nil, nil, options) { view_or_string.to_s }
|
17
|
-
end
|
61
|
+
roy.send(:extend, InstanceMethods)
|
62
|
+
end
|
63
|
+
|
64
|
+
module InstanceMethods
|
18
65
|
|
19
|
-
|
20
|
-
|
66
|
+
# Render the given template or string with the selected engine.
|
67
|
+
#
|
68
|
+
# Views are looked for inside the +roy.conf.views+ directory.
|
69
|
+
# Files should have an extension matching the selected engine.
|
70
|
+
# If you want to use sub-directories, you have to use the
|
71
|
+
# +:"subdir/file.ext"+ syntax.
|
72
|
+
#
|
73
|
+
# @see https://github.com/rtomayko/tilt/blob/master/README.md
|
74
|
+
# @see https://github.com/rtomayko/tilt/blob/master/TEMPLATES.md
|
75
|
+
#
|
76
|
+
# @param [Symbol] engine the name of the rendering engine. Must be
|
77
|
+
# supported by Tilt.
|
78
|
+
# @param [Symbol] view_or_string a template file.
|
79
|
+
# @param [String] view_or_string a template string.
|
80
|
+
# @param [Hash] params locals for Tilt::Template#render.
|
81
|
+
# @param [Proc] block a block to execute when using +yield+ in the
|
82
|
+
# template.
|
83
|
+
def render(engine, view_or_string, params={}, &block)
|
84
|
+
options = conf.render || {}
|
85
|
+
template = case view_or_string
|
86
|
+
when Symbol
|
87
|
+
file = [view_or_string.to_s, engine].map(&:to_s).join('.')
|
88
|
+
dir = conf.views || 'views'
|
89
|
+
Tilt.new(File.join(dir, file), nil, options)
|
90
|
+
else
|
91
|
+
Tilt[engine].new(nil, nil, options) { view_or_string.to_s }
|
92
|
+
end
|
93
|
+
|
94
|
+
template.render(app, params, &block)
|
21
95
|
end
|
96
|
+
|
22
97
|
end
|
23
98
|
|
24
99
|
end
|
data/lib/roy/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-02-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
16
|
-
requirement: &
|
16
|
+
requirement: &13775240 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *13775240
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: minitest
|
27
|
-
requirement: &
|
27
|
+
requirement: &13774520 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *13774520
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rack-test
|
38
|
-
requirement: &
|
38
|
+
requirement: &13792140 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *13792140
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: tilt
|
49
|
-
requirement: &
|
49
|
+
requirement: &13791400 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *13791400
|
58
58
|
description: ! 'roy is a small library which allows every Ruby object to be used
|
59
59
|
|
60
60
|
as a Rack application.'
|
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
111
|
version: '0'
|
112
112
|
requirements: []
|
113
113
|
rubyforge_project: roy
|
114
|
-
rubygems_version: 1.8.
|
114
|
+
rubygems_version: 1.8.15
|
115
115
|
signing_key:
|
116
116
|
specification_version: 3
|
117
117
|
summary: make your objects REST-friendly
|