lotus-router 0.4.0 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b3fcb5db6c1bdb046aeb93c5d0950301d5ed551d
4
- data.tar.gz: 577b5c170f3d469369ce4c43c11782f6f9d6ea3c
3
+ metadata.gz: fe3bedc422dfc753499bc3b622eae9991fbb5f6d
4
+ data.tar.gz: 04092313d4a1f9c19f83e4f555b4da56394b33ba
5
5
  SHA512:
6
- metadata.gz: 189025ab49239109b74a6f939585d2cdc56b7568a9864c0a82af39fc166a36b8f4f4ae7e5335a53b5ca3bcadd2120b75705ca6dc8d12a1b9bf05501aaa45f652
7
- data.tar.gz: 339c1ac13cb39971e7594675646b2c7f2a0baafa96a5bd7b44c16be0ce291d089857abbd797ab6fa6be44fa1b7a279c1d159562acd1d46c60ba97c43779d102f
6
+ metadata.gz: e0481beec0347d4f748fddd153eefa13b7e6460bf9ce16901179d7930fcecd2a6f2196e954d84a37a8c7b3f9355da2eb3b3ba6ad46ca404534759ca7fbbabd81
7
+ data.tar.gz: cf5c52860e529475867d0f4df858df214acd206054912fa82849b2d973ecf5a46d84292609599d0496fb04270f11f0b01bfb5784fabd0d625ef7348dee0ea69d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # Lotus::Router
2
2
  Rack compatible HTTP router for Ruby
3
3
 
4
+ ## v0.4.1 - 2015-06-23
5
+ ### Added
6
+ - [Alfonso Uceda Pompa] Force SSL (eg `Lotus::Router.new(force_ssl: true`).
7
+ - [Alfonso Uceda Pompa] Allow router to accept a `:prefix` option, in order to generate prefixed routes.
8
+
4
9
  ## v0.4.0 - 2015-05-15
5
10
  ### Added
6
11
  - [Alfonso Uceda Pompa] Nested RESTful resource(s)
data/lib/lotus/router.rb CHANGED
@@ -13,12 +13,11 @@ module Lotus
13
13
  #
14
14
  # endpoint = ->(env) { [200, {}, ['Welcome to Lotus::Router!']] }
15
15
  # router = Lotus::Router.new do
16
- # get '/', to: endpoint
16
+ # get '/', to: endpoint # => get and head requests
17
17
  # post '/', to: endpoint
18
18
  # put '/', to: endpoint
19
19
  # patch '/', to: endpoint
20
20
  # delete '/', to: endpoint
21
- # head '/', to: endpoint
22
21
  # options '/', to: endpoint
23
22
  # trace '/', to: endpoint
24
23
  # end
@@ -1,6 +1,6 @@
1
1
  module Lotus
2
2
  class Router
3
3
  # @since 0.1.0
4
- VERSION = '0.4.0'.freeze
4
+ VERSION = '0.4.1'.freeze
5
5
  end
6
6
  end
@@ -0,0 +1,209 @@
1
+ require 'rack/request'
2
+
3
+ module Lotus
4
+ module Routing
5
+ # Force ssl
6
+ #
7
+ # Redirect response to the secure equivalent resource (https)
8
+ #
9
+ # @since 0.4.1
10
+ # @api private
11
+ class ForceSsl
12
+ # Https scheme
13
+ #
14
+ # @since 0.4.1
15
+ # @api private
16
+ SSL_SCHEME = 'https'.freeze
17
+
18
+ # @since 0.4.1
19
+ # @api private
20
+ HTTPS = 'HTTPS'.freeze
21
+
22
+ # @since 0.4.1
23
+ # @api private
24
+ ON = 'on'.freeze
25
+
26
+ # Location header
27
+ #
28
+ # @since 0.4.1
29
+ # @api private
30
+ LOCATION_HEADER = 'Location'.freeze
31
+
32
+ # Default http port
33
+ #
34
+ # @since 0.4.1
35
+ # @api private
36
+ DEFAULT_HTTP_PORT = 80
37
+
38
+ # Default ssl port
39
+ #
40
+ # @since 0.4.1
41
+ # @api private
42
+ DEFAULT_SSL_PORT = 443
43
+
44
+ # Moved Permanently http code
45
+ #
46
+ # @since 0.4.1
47
+ # @api private
48
+ MOVED_PERMANENTLY_HTTP_CODE = 301
49
+
50
+ # Temporary Redirect http code
51
+ #
52
+ # @since 0.4.1
53
+ # @api private
54
+ TEMPORARY_REDIRECT_HTTP_CODE = 307
55
+
56
+ # @since 0.4.1
57
+ # @api private
58
+ HTTP_X_FORWARDED_SSL = 'HTTP_X_FORWARDED_SSL'.freeze
59
+
60
+ # @since 0.4.1
61
+ # @api private
62
+ HTTP_X_FORWARDED_SCHEME = 'HTTP_X_FORWARDED_SCHEME'.freeze
63
+
64
+ # @since 0.4.1
65
+ # @api private
66
+ HTTP_X_FORWARDED_PROTO = 'HTTP_X_FORWARDED_PROTO'.freeze
67
+
68
+ # @since 0.4.1
69
+ # @api private
70
+ HTTP_X_FORWARDED_PROTO_SEPARATOR = ','.freeze
71
+
72
+ # @since 0.4.1
73
+ # @api private
74
+ RACK_URL_SCHEME = 'rack.url_scheme'.freeze
75
+
76
+ # @since 0.4.1
77
+ # @api private
78
+ REQUEST_METHOD = 'REQUEST_METHOD'.freeze
79
+
80
+ # @since 0.4.1
81
+ # @api private
82
+ IDEMPOTENT_METHODS = ['GET', 'HEAD'].freeze
83
+
84
+ EMPTY_BODY = ''.freeze
85
+
86
+ # Initialize ForceSsl.
87
+ #
88
+ # @param active [Boolean] activate redirection to SSL
89
+ # @param options [Hash] set of options
90
+ # @option options [String] :host
91
+ # @option options [Integer] :port
92
+ #
93
+ # @since 0.4.1
94
+ # @api private
95
+ def initialize(active, options = {})
96
+ @active = active
97
+ @host = options[:host]
98
+ @port = options[:port]
99
+
100
+ _redefine_call
101
+ end
102
+
103
+ # Set 301 status and Location header if this feature is activated.
104
+ #
105
+ # @param env [Hash] a Rack env instance
106
+ #
107
+ # @return [Array]
108
+ #
109
+ # @see Lotus::Routing::HttpRouter#call
110
+ #
111
+ # @since 0.4.1
112
+ # @api private
113
+ def call(env)
114
+ end
115
+
116
+ # Check if router has to force the response with ssl
117
+ #
118
+ # @return [Boolean]
119
+ #
120
+ # @since 0.4.1
121
+ # @api private
122
+ def force?(env)
123
+ !ssl?(env)
124
+ end
125
+
126
+ private
127
+
128
+ # @since 0.4.1
129
+ # @api private
130
+ attr_reader :host
131
+
132
+ # Return full url to redirect
133
+ #
134
+ # @param env [Hash] Rack env
135
+ #
136
+ # @return [String]
137
+ #
138
+ # @since 0.4.1
139
+ # @api private
140
+ def full_url(env)
141
+ "#{ SSL_SCHEME }://#{ host }:#{ port }#{ ::Rack::Request.new(env).fullpath }"
142
+ end
143
+
144
+ # Return redirect code
145
+ #
146
+ # @param env [Hash] Rack env
147
+ #
148
+ # @return [Integer]
149
+ #
150
+ # @since 0.4.1
151
+ # @api private
152
+ def redirect_code(env)
153
+ if IDEMPOTENT_METHODS.include?(env[REQUEST_METHOD])
154
+ MOVED_PERMANENTLY_HTTP_CODE
155
+ else
156
+ TEMPORARY_REDIRECT_HTTP_CODE
157
+ end
158
+ end
159
+
160
+ # Return correct default port for full url
161
+ #
162
+ # @return [Integer]
163
+ #
164
+ # @since 0.4.1
165
+ # @api private
166
+ def port
167
+ if @port == DEFAULT_HTTP_PORT
168
+ DEFAULT_SSL_PORT
169
+ else
170
+ @port
171
+ end
172
+ end
173
+
174
+ # @since 0.4.1
175
+ # @api private
176
+ def _redefine_call
177
+ return unless @active
178
+
179
+ define_singleton_method :call do |env|
180
+ [redirect_code(env), { LOCATION_HEADER => full_url(env) }, EMPTY_BODY] if force?(env)
181
+ end
182
+ end
183
+
184
+ # Adapted from Rack::Request#scheme
185
+ #
186
+ # @since 0.4.1
187
+ # @api private
188
+ def scheme(env)
189
+ if env[HTTPS] == ON
190
+ SSL_SCHEME
191
+ elsif env[HTTP_X_FORWARDED_SSL] == ON
192
+ SSL_SCHEME
193
+ elsif env[HTTP_X_FORWARDED_SCHEME]
194
+ env[HTTP_X_FORWARDED_SCHEME]
195
+ elsif env[HTTP_X_FORWARDED_PROTO]
196
+ env[HTTP_X_FORWARDED_PROTO].split(HTTP_X_FORWARDED_PROTO_SEPARATOR)[0]
197
+ else
198
+ env[RACK_URL_SCHEME]
199
+ end
200
+ end
201
+
202
+ # @since 0.4.1
203
+ # @api private
204
+ def ssl?(env)
205
+ scheme(env) == SSL_SCHEME
206
+ end
207
+ end
208
+ end
209
+ end
@@ -3,6 +3,8 @@ require 'lotus/utils/io'
3
3
  require 'lotus/routing/endpoint_resolver'
4
4
  require 'lotus/routing/route'
5
5
  require 'lotus/routing/parsers'
6
+ require 'lotus/routing/force_ssl'
7
+ require 'lotus/utils/path_prefix'
6
8
 
7
9
  Lotus::Utils::IO.silence_warnings do
8
10
  HttpRouter::Route::VALID_HTTP_VERBS = %w{GET POST PUT PATCH DELETE HEAD OPTIONS TRACE}
@@ -37,12 +39,14 @@ module Lotus
37
39
  def initialize(options = {}, &blk)
38
40
  super(options, &nil)
39
41
 
40
- @default_scheme = options[:scheme] if options[:scheme]
41
- @default_host = options[:host] if options[:host]
42
- @default_port = options[:port] if options[:port]
43
- @route_class = options[:route] || Routing::Route
44
- @resolver = options[:resolver] || Routing::EndpointResolver.new(options)
45
- @parsers = Routing::Parsers.new(options[:parsers])
42
+ @default_scheme = options[:scheme] if options[:scheme]
43
+ @default_host = options[:host] if options[:host]
44
+ @default_port = options[:port] if options[:port]
45
+ @route_class = options[:route] || Routing::Route
46
+ @resolver = options[:resolver] || Routing::EndpointResolver.new(options)
47
+ @parsers = Routing::Parsers.new(options[:parsers])
48
+ @prefix = Utils::PathPrefix.new(options[:prefix] || '')
49
+ @force_ssl = Lotus::Routing::ForceSsl.new(!!options[:force_ssl], host: @default_host, port: @default_port)
46
50
  end
47
51
 
48
52
  # Separator between controller and action name.
@@ -85,6 +89,66 @@ module Lotus
85
89
  _rescue_url_recognition { super }
86
90
  end
87
91
 
92
+ # Support for GET HTTP verb
93
+ #
94
+ # @see Lotus::Router#options
95
+ #
96
+ # @since 0.4.1
97
+ # @api private
98
+ def get(path, options = {}, &blk)
99
+ super(@prefix.join(path), options, &blk)
100
+ end
101
+
102
+ # Support for POST HTTP verb
103
+ #
104
+ # @see Lotus::Router#post
105
+ #
106
+ # @since 0.4.1
107
+ # @api private
108
+ def post(path, options = {}, &blk)
109
+ super(@prefix.join(path), options, &blk)
110
+ end
111
+
112
+ # Support for PUT HTTP verb
113
+ #
114
+ # @see Lotus::Router#put
115
+ #
116
+ # @since 0.4.1
117
+ # @api private
118
+ def put(path, options = {}, &blk)
119
+ super(@prefix.join(path), options, &blk)
120
+ end
121
+
122
+ # Support for PATCH HTTP verb
123
+ #
124
+ # @see Lotus::Router#patch
125
+ #
126
+ # @since 0.4.1
127
+ # @api private
128
+ def patch(path, options = {}, &blk)
129
+ super(@prefix.join(path), options, &blk)
130
+ end
131
+
132
+ # Support for DELETE HTTP verb
133
+ #
134
+ # @see Lotus::Router#delete
135
+ #
136
+ # @since 0.4.1
137
+ # @api private
138
+ def delete(path, options = {}, &blk)
139
+ super(@prefix.join(path), options, &blk)
140
+ end
141
+
142
+ # Support for TRACE HTTP verb
143
+ #
144
+ # @see Lotus::Router#trace
145
+ #
146
+ # @since 0.4.1
147
+ # @api private
148
+ def trace(path, options = {}, &blk)
149
+ super(@prefix.join(path), options, &blk)
150
+ end
151
+
88
152
  # Support for OPTIONS HTTP verb
89
153
  #
90
154
  # @see Lotus::Router#options
@@ -92,7 +156,7 @@ module Lotus
92
156
  # @since 0.1.0
93
157
  # @api private
94
158
  def options(path, options = {}, &blk)
95
- add_with_request_method(path, :options, options, &blk)
159
+ add_with_request_method(@prefix.join(path), :options, options, &blk)
96
160
  end
97
161
 
98
162
  # Allow to mount a Rack app
@@ -109,7 +173,11 @@ module Lotus
109
173
 
110
174
  # @api private
111
175
  def raw_call(env, &blk)
112
- super(@parsers.call(env))
176
+ if response = @force_ssl.call(env)
177
+ response
178
+ else
179
+ super(@parsers.call(env))
180
+ end
113
181
  end
114
182
 
115
183
  # @api private
@@ -57,6 +57,12 @@ module Lotus
57
57
  super(@name.join(path), options, &endpoint)
58
58
  end
59
59
 
60
+ # @api private
61
+ # @since 0.1.0
62
+ def options(path, options = {}, &endpoint)
63
+ super(@name.join(path), options, &endpoint)
64
+ end
65
+
60
66
  # @api private
61
67
  # @since 0.1.0
62
68
  def resource(name, options = {})
data/lotus-router.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.required_ruby_version = '>= 2.0.0'
21
21
 
22
22
  spec.add_dependency 'http_router', '~> 0.11'
23
- spec.add_dependency 'lotus-utils', '~> 0.4', '>= 0.4.1'
23
+ spec.add_dependency 'lotus-utils', '~> 0.5'
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.5'
26
26
  spec.add_development_dependency 'minitest', '~> 5'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lotus-router
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-15 00:00:00.000000000 Z
11
+ date: 2015-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http_router
@@ -30,20 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.4'
34
- - - ">="
35
- - !ruby/object:Gem::Version
36
- version: 0.4.1
33
+ version: '0.5'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
38
  - - "~>"
42
39
  - !ruby/object:Gem::Version
43
- version: '0.4'
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: 0.4.1
40
+ version: '0.5'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: bundler
49
43
  requirement: !ruby/object:Gem::Requirement
@@ -101,6 +95,7 @@ files:
101
95
  - lib/lotus/router/version.rb
102
96
  - lib/lotus/routing/endpoint.rb
103
97
  - lib/lotus/routing/endpoint_resolver.rb
98
+ - lib/lotus/routing/force_ssl.rb
104
99
  - lib/lotus/routing/http_router.rb
105
100
  - lib/lotus/routing/namespace.rb
106
101
  - lib/lotus/routing/parsers.rb
@@ -135,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
130
  version: '0'
136
131
  requirements: []
137
132
  rubyforge_project:
138
- rubygems_version: 2.4.5
133
+ rubygems_version: 2.4.8
139
134
  signing_key:
140
135
  specification_version: 4
141
136
  summary: Rack compatible HTTP router for Ruby and Lotus