utopia 2.8.2 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a40f8fb67b26f53edba8a76b91c2dddc730127641e918c5f8b9f79b5f20a5275
4
- data.tar.gz: 57ff2d40871d3a5b8e76e4ddf25a0aafc2bebe87e11e15469b08419e78e3124e
3
+ metadata.gz: 05f9ea2c2313177fe0ddab9681776ce465160016ba76ddf961ce32c90613031d
4
+ data.tar.gz: 24cc21d33830e008f34354bf95eaf52bce0a83bde857ba59a03c3e120e1a84e7
5
5
  SHA512:
6
- metadata.gz: 0cf61f5628b5bf6e7386059238d14f141f27a2eea1f7b5f2f0204156fba2538caf8f0850ecd13646fe663a3b7b3044790f3744799abfa3ad5bea13ffc4ac8ab9
7
- data.tar.gz: 43796a9d6ebde85e159139c4dbdecac570c1c07e1f162c214a092cc3b726781bcae4d4834cf0e22d5327eff58473687cbc869138e0ea4fe055d41af57bbdae36
6
+ metadata.gz: 076044052516cd4bf26f476e2dbca23fcf5f9e49673b5f169f317d70ae1b6d560e5c2bf4578e8cdcd0ed368fe4eb328e7d1d083269406f67459c4a7f48f37b33
7
+ data.tar.gz: 07056aba9f2533e1fee4e60f337a2d1cf2b048bca510488c447c1b528ab7d0ee2df37dc8ab32d5d8e4387197eefdc66663efca291d00359134758b158cb73702
@@ -9,13 +9,14 @@ before_install:
9
9
 
10
10
  matrix:
11
11
  include:
12
- - rvm: 2.3
13
12
  - rvm: 2.4
14
13
  - rvm: 2.5
15
14
  - rvm: 2.6
16
15
  env: BENCHMARK=true
17
16
  - rvm: 2.6
18
17
  env: COVERAGE=BriefSummary,Coveralls
18
+ - rvm: 2.6
19
+ os: osx
19
20
  - rvm: ruby-head
20
21
  - rvm: jruby-head
21
22
  - rvm: truffleruby
data/README.md CHANGED
@@ -41,7 +41,7 @@ Create a new site:
41
41
 
42
42
  ## Usage
43
43
 
44
- There is an excellent documentation wiki included with the source code. Simply clone this repository and `rake documentation:server`. This documentation wiki is editable, so feel free to submit a PR with improvements.
44
+ There is an excellent [documentation wiki](https://ioquatix.github.io/utopia/) included with the source code. Simply clone this repository and `rake documentation:server`. This documentation wiki is editable, so feel free to submit a PR with improvements.
45
45
 
46
46
  ## Contributing
47
47
 
@@ -14,6 +14,7 @@ gem "kramdown-parser-gfm"
14
14
  group :development do
15
15
  # For `rake server`:
16
16
  gem "guard-falcon"
17
+ gem "falcon"
17
18
 
18
19
  # For `rake console`:
19
20
  gem "pry"
@@ -22,8 +23,3 @@ group :development do
22
23
  # For `rspec` testing:
23
24
  gem "rspec"
24
25
  end
25
-
26
- group :production do
27
- # Used for passenger-config to restart server after deployment:
28
- gem "passenger"
29
- end
@@ -4,7 +4,7 @@ Utopia is designed to make deployment to remote servers easy.
4
4
 
5
5
  ## Deployment
6
6
 
7
- The preferred method of deployment to a production server is via git. The `utopia` command assists with setup of a remote git repository on the server. It will setup a `git` `post-update` hook which will deploy the site correctly and restart passenger for that site.
7
+ The preferred method of deployment to a production server is via git. The `utopia` command assists with setup of a remote git repository on the server. It will setup a `git` `post-update` hook which will deploy the site correctly and restart the application server for that site.
8
8
 
9
9
  To setup a server for deployment:
10
10
 
@@ -37,31 +37,7 @@ When you run `rake` tasks or spawn a server, the values in `config/environment.y
37
37
 
38
38
  ## Platform
39
39
 
40
- The best deployment platform for Utopia is Linux. Specifically, [Arch Linux](https://www.archlinux.org/) with the following packages:
41
-
42
- - [nginx-mainline-passenger](https://aur.archlinux.org/packages/nginx-mainline-passenger/)
43
- - [passenger-nginx-module](https://aur.archlinux.org/packages/passenger-nginx-module/)
44
-
45
- There have been issues with the official packages and thus these packages were developed and tested with Utopia deployment in mind.
46
-
47
- ### Sample Nginx Configuration
48
-
49
- Create a configuration file for your site, e.g. `/etc/nginx/sites/www.example.com`:
50
-
51
- ```nginx
52
- server {
53
- listen 80;
54
- server_name www.example.com;
55
- root /srv/http/www.example.com/public;
56
- passenger_enabled on;
57
- }
58
-
59
- server {
60
- listen 80;
61
- server_name example.com;
62
- rewrite ^ http://www.example.com$uri permanent;
63
- }
64
- ```
40
+ The best deployment platform for Utopia is Linux, using [falcon](https://github.com/socketry/falcon).
65
41
 
66
42
  ### Sudo Setup
67
43
 
@@ -1,6 +1,6 @@
1
1
  # Testing
2
2
 
3
- Utopia websites include a default set of tests, and associated `rake test` tasks. These specs can test against the actual running website. By default, `simplecov` is included for coverage testing.
3
+ Utopia websites include a default set of tests, and associated `rake test` tasks. These specs can test against the actual running website. By default, [covered](https://github.com/socketry/covered) is included for coverage testing.
4
4
 
5
5
  ```bash
6
6
  $ rake coverage test
@@ -97,13 +97,13 @@ module Utopia
97
97
  def to_anchor(**options)
98
98
  Trenni::Builder.fragment(options[:builder]) do |builder|
99
99
  if href?
100
- a_attributes = {
100
+ attributes = {
101
101
  :class => options.fetch(:class, 'link'),
102
102
  :href => relative_href(options[:base]),
103
103
  :target => options.fetch(:target, @info[:target])
104
104
  }
105
105
 
106
- builder.inline('a', a_attributes) do
106
+ builder.inline('a', attributes) do
107
107
  builder.text(options[:content] || title)
108
108
  end
109
109
  else
@@ -36,7 +36,7 @@ module Utopia
36
36
  def call(env)
37
37
  response = @app.call(env)
38
38
 
39
- unless response[2].empty? or response[1].include?(Rack::CONTENT_LENGTH)
39
+ unless response[2]&.empty? or response[1].include?(Rack::CONTENT_LENGTH)
40
40
  if content_length = self.content_length_of(response[2])
41
41
  response[1][Rack::CONTENT_LENGTH] = content_length
42
42
  end
@@ -81,7 +81,12 @@ module Utopia
81
81
  def respond!(response)
82
82
  throw :response, response
83
83
  end
84
-
84
+
85
+ # Respond with the response, but only if it's not nil.
86
+ def respond?(response)
87
+ respond!(response) if response
88
+ end
89
+
85
90
  # This will cause the controller middleware to pass on the request.
86
91
  def ignore!
87
92
  throw :response, nil
@@ -180,14 +180,10 @@ module Utopia
180
180
 
181
181
  # Set the Vary: header on the response to indicate that this response should include the header in the cache key.
182
182
  def vary(env, response)
183
- headers = response[1]
183
+ headers = response[1].to_a
184
184
 
185
185
  # This response was based on the Accept-Language header:
186
- if headers['Vary']
187
- headers['Vary'] += ',Accept-Language'
188
- else
189
- headers['Vary'] = 'Accept-Language'
190
- end
186
+ headers << ['Vary', 'Accept-Language']
191
187
 
192
188
  # Althought this header is generally not supported, we supply it anyway as it is useful for debugging:
193
189
  if locale = env[CURRENT_LOCALE_KEY]
@@ -18,8 +18,6 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'logger'
22
-
23
21
  require_relative 'http'
24
22
  require_relative 'path'
25
23
 
@@ -126,7 +126,7 @@ module Utopia
126
126
 
127
127
  data = encrypt(session_hash.values)
128
128
 
129
- commit(data, headers)
129
+ commit(data, values[:updated_at], headers)
130
130
  end
131
131
  end
132
132
 
@@ -165,20 +165,26 @@ module Utopia
165
165
  if values[:user_agent] != request.user_agent
166
166
  raise PayloadError, "Invalid session because supplied user agent #{request.user_agent.inspect} does not match session user agent #{values[:user_agent].inspect}!"
167
167
  end
168
+
169
+ if expires_at = expires(values[:updated_at])
170
+ if expires_at < Time.now.utc
171
+ raise PayloadError, "Expired session cookie, user agent submitted a cookie that should have expired at #{expires_at}."
172
+ end
173
+ end
168
174
 
169
175
  return true
170
176
  end
171
177
 
172
- def expires
178
+ def expires(updated_at=Time.now.utc)
173
179
  if @expires_after
174
- return Time.now.utc + @expires_after
180
+ return updated_at + @expires_after
175
181
  end
176
182
  end
177
183
 
178
- def commit(value, headers)
184
+ def commit(value, updated_at, headers)
179
185
  cookie = {
180
186
  value: value,
181
- expires: expires
187
+ expires: expires(updated_at)
182
188
  }.merge(@cookie_defaults)
183
189
 
184
190
  Rack::Utils.set_cookie_header!(headers, @cookie_name, cookie)
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Utopia
22
- VERSION = "2.8.2"
22
+ VERSION = "2.9.0"
23
23
  end
@@ -23,8 +23,3 @@ group :development do
23
23
  gem "rspec"
24
24
  gem "covered"
25
25
  end
26
-
27
- group :production do
28
- # Used for passenger-config to restart server after deployment:
29
- gem "passenger"
30
- end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env -S falcon host
2
+
3
+ load :rack, :self_signed_tls, :supervisor
4
+
5
+ rack 'utopia.localhost', :self_signed_tls
6
+ supervisor
@@ -23,7 +23,7 @@
23
23
  <div>
24
24
  <i class="fa fa-server"></i>
25
25
  <h2>Batteries included</h2>
26
- <p>Utopia includes both a recommended development model and a server deployment model out of the box. This is exposed via the <code>utopia</code> command. We recommend use of <a href="https://www.nginx.com">Nginx</a> and <a href="https://www.phusionpassenger.com">Passenger</a> for server side deployment.</p>
26
+ <p>Utopia includes both a recommended development model and a server deployment model out of the box. This is exposed via the <code>utopia</code> command. We recommend use of <a href="https://github.com/socketry/falcon">Falcon</a> for server side deployment.</p>
27
27
  </div>
28
28
 
29
29
  <div>
@@ -6,8 +6,7 @@ end
6
6
 
7
7
  desc 'Restart the application server'
8
8
  task :restart do
9
- # This task is run after the deployment task above.
10
- if passenger_config = `which passenger-config`.chomp!
11
- sh(passenger_config, 'restart-app', '--ignore-passenger-not-running', SITE_ROOT.to_s)
9
+ if falcon = `which falcon`.chomp! and File.exist?("supervisor.ipc")
10
+ sh(falcon, 'supervisor', 'restart')
12
11
  end
13
12
  end
@@ -1,12 +1,10 @@
1
1
 
2
2
  require "rspec/core/rake_task"
3
3
 
4
- RSpec::Core::RakeTask.new(:test) do |task|
5
- task.rspec_opts = %w{--require simplecov} if ENV['COVERAGE']
6
- end
4
+ RSpec::Core::RakeTask.new(:test)
7
5
 
8
6
  task :coverage do
9
- ENV['COVERAGE'] = 'y'
7
+ ENV['COVERAGE'] = 'PartialSummary'
10
8
  end
11
9
 
12
10
  desc 'Start the development server.'
@@ -1,6 +1,6 @@
1
1
 
2
2
  desc 'Set up the environment for running your web application'
3
- task :environment do |task|
3
+ task :environment => :log do |task|
4
4
  require SITE_ROOT + 'config/environment'
5
5
 
6
6
  # We ensure this is part of the shell environment so if other commands are invoked they will work correctly.
@@ -11,7 +11,7 @@ task :environment do |task|
11
11
  if ENV['UTOPIA_SESSION_SECRET'].nil?
12
12
  require 'securerandom'
13
13
 
14
- warn 'Generating transient session key for development...'
14
+ Utopia.logger.warn 'Generating transient session key for development...'
15
15
  ENV['UTOPIA_SESSION_SECRET'] = SecureRandom.hex(32)
16
16
  end
17
17
  end
@@ -1,5 +1,6 @@
1
1
 
2
2
  require 'covered/rspec'
3
+ require 'async/rspec'
3
4
 
4
5
  RSpec.configure do |config|
5
6
  # Enable flags like --only-failures and --next-failure
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'rack/test'
24
+ require 'utopia/controller'
25
+
26
+ require 'async/websocket/client'
27
+ require 'async/websocket/adapters/rack'
28
+
29
+ require 'falcon/server'
30
+ require 'falcon/adapters/rack'
31
+
32
+ require 'async/http/client'
33
+ require 'async/http/endpoint'
34
+
35
+ RSpec.describe Utopia::Controller do
36
+ context Async::WebSocket::Client do
37
+ include Rack::Test::Methods
38
+ include_context Async::RSpec::Reactor
39
+
40
+ let(:endpoint) {Async::HTTP::Endpoint.parse("http://localhost:7050/server/events")}
41
+ let(:app) {Rack::Builder.parse_file(File.expand_path('websocket_spec.ru', __dir__)).first}
42
+ let(:server) {Falcon::Server.new(Falcon::Server.middleware(app), endpoint)}
43
+ let(:client) {Async::HTTP::Client.new(endpoint)}
44
+
45
+ let!(:server_task) do
46
+ reactor.async do
47
+ server.run
48
+ end
49
+ end
50
+
51
+ after do
52
+ server_task.stop
53
+ end
54
+
55
+ it "fails for normal requests" do
56
+ get "/server/events"
57
+
58
+ expect(last_response.status).to be == 400
59
+ end
60
+
61
+ it "can connect to websocket" do
62
+ Async::WebSocket::Client.connect(endpoint) do |connection|
63
+ expect(connection.read).to be == {type: "test", data: "Hello World"}
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,4 @@
1
+
2
+ use Utopia::Controller, root: File.expand_path('websocket_spec', __dir__)
3
+
4
+ run lambda {|env| [404, {}, []]}
@@ -0,0 +1,10 @@
1
+
2
+ prepend Actions
3
+
4
+ on 'events' do |request|
5
+ upgrade = Async::WebSocket::Adapters::Rack.open(request.env) do |connection|
6
+ connection.write({type: "test", data: "Hello World"})
7
+ end
8
+
9
+ respond?(upgrade) or fail!
10
+ end
@@ -102,6 +102,15 @@ module Utopia::SessionSpec
102
102
  get "/session-get?key=foo"
103
103
  expect(last_response.body).to be == ""
104
104
  end
105
+
106
+ it "should fail if expired cookie is sent with the request" do
107
+ session_cookie = last_response['Set-Cookie'].split(';')[0]
108
+ sleep 6 # sleep longer than the session timeout
109
+ header 'Cookie', session_cookie
110
+
111
+ get "/session-get?key=foo"
112
+ expect(last_response.body).to be == ""
113
+ end
105
114
 
106
115
  it "shouldn't fail if ip address is changed" do
107
116
  # Change user agent:
@@ -1,7 +1,7 @@
1
1
 
2
2
  use Utopia::Session,
3
3
  secret: "97111cabf4c1a5e85b8029cf7c61aa44424fc24a",
4
- expires_after: 3600 * 48,
4
+ expires_after: 5,
5
5
  update_timeout: 1
6
6
 
7
7
  run lambda { |env|
@@ -38,9 +38,12 @@ Gem::Specification.new do |spec|
38
38
 
39
39
  spec.add_dependency 'concurrent-ruby', '~> 1.0'
40
40
 
41
+ spec.add_development_dependency 'falcon'
42
+ spec.add_development_dependency 'async-rspec'
43
+ spec.add_development_dependency 'async-websocket'
44
+
41
45
  spec.add_development_dependency 'covered'
42
46
  spec.add_development_dependency 'bundler'
43
47
  spec.add_development_dependency 'rspec', '~> 3.6'
44
- spec.add_development_dependency 'falcon'
45
48
  spec.add_development_dependency 'rake'
46
49
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: utopia
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.2
4
+ version: 2.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-29 00:00:00.000000000 Z
11
+ date: 2019-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trenni
@@ -137,7 +137,7 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '1.0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: covered
140
+ name: falcon
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
@@ -151,7 +151,7 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
- name: bundler
154
+ name: async-rspec
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - ">="
@@ -165,21 +165,35 @@ dependencies:
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  - !ruby/object:Gem::Dependency
168
- name: rspec
168
+ name: async-websocket
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - "~>"
171
+ - - ">="
172
172
  - !ruby/object:Gem::Version
173
- version: '3.6'
173
+ version: '0'
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - "~>"
178
+ - - ">="
179
179
  - !ruby/object:Gem::Version
180
- version: '3.6'
180
+ version: '0'
181
181
  - !ruby/object:Gem::Dependency
182
- name: falcon
182
+ name: covered
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: bundler
183
197
  requirement: !ruby/object:Gem::Requirement
184
198
  requirements:
185
199
  - - ">="
@@ -192,6 +206,20 @@ dependencies:
192
206
  - - ">="
193
207
  - !ruby/object:Gem::Version
194
208
  version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: rspec
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '3.6'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '3.6'
195
223
  - !ruby/object:Gem::Dependency
196
224
  name: rake
197
225
  requirement: !ruby/object:Gem::Requirement
@@ -617,6 +645,7 @@ files:
617
645
  - setup/site/config.ru
618
646
  - setup/site/config/README.md
619
647
  - setup/site/config/environment.rb
648
+ - setup/site/falcon.rb
620
649
  - setup/site/lib/readme.txt
621
650
  - setup/site/pages/_heading.xnode
622
651
  - setup/site/pages/_page.xnode
@@ -701,6 +730,9 @@ files:
701
730
  - spec/utopia/controller/rewrite_spec.rb
702
731
  - spec/utopia/controller/sequence_spec.rb
703
732
  - spec/utopia/controller/variables_spec.rb
733
+ - spec/utopia/controller/websocket_spec.rb
734
+ - spec/utopia/controller/websocket_spec.ru
735
+ - spec/utopia/controller/websocket_spec/server/controller.rb
704
736
  - spec/utopia/exceptions/handler_spec.rb
705
737
  - spec/utopia/exceptions/handler_spec.ru
706
738
  - spec/utopia/exceptions/handler_spec/controller.rb
@@ -760,7 +792,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
760
792
  - !ruby/object:Gem::Version
761
793
  version: '0'
762
794
  requirements: []
763
- rubygems_version: 3.0.3
795
+ rubygems_version: 3.0.2
764
796
  signing_key:
765
797
  specification_version: 4
766
798
  summary: Utopia is a framework for building dynamic content-driven websites.
@@ -828,6 +860,9 @@ test_files:
828
860
  - spec/utopia/controller/rewrite_spec.rb
829
861
  - spec/utopia/controller/sequence_spec.rb
830
862
  - spec/utopia/controller/variables_spec.rb
863
+ - spec/utopia/controller/websocket_spec.rb
864
+ - spec/utopia/controller/websocket_spec.ru
865
+ - spec/utopia/controller/websocket_spec/server/controller.rb
831
866
  - spec/utopia/exceptions/handler_spec.rb
832
867
  - spec/utopia/exceptions/handler_spec.ru
833
868
  - spec/utopia/exceptions/handler_spec/controller.rb