rack-unpoly 0.4.0
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 +7 -0
- data/README.md +77 -0
- data/Rakefile +18 -0
- data/lib/rack/unpoly.rb +8 -0
- data/lib/rack/unpoly/inspector.rb +87 -0
- data/lib/rack/unpoly/middleware.rb +57 -0
- data/lib/sinatra/unpoly.rb +61 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: '098a6137f012df7a85d6e681805d1051c39cd929'
|
4
|
+
data.tar.gz: 0d89558009d7382033b662c29b7db77888116d01
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 74e384be3125a6c1261d82af9e14f600a4f7622d3a2e36d960f3b27a82b326c342abe87c3c183d78acc522245632a29517c3ef2e062ccab67b1ad9a274796deb
|
7
|
+
data.tar.gz: 66aad412ab1a9cef65fdfb356df68f851efb3a1477433ce65945fd5e2caa80a51f24bac5adb01fd675e90f1b4a4666981d3447d0f4c6f1081cbf11257bf6ca02
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Unpoly for Rack & Sinatra
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem "rack-unpoly"
|
9
|
+
```
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rack-unpoly
|
18
|
+
|
19
|
+
## Usage in a Rails application
|
20
|
+
|
21
|
+
Use the official [Unpoly](https://rubygems.org/gems/unpoly-rails) gem from Makandra.
|
22
|
+
|
23
|
+
## Usage in a Sinatra application
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require "sinatra/base"
|
27
|
+
require "sinatra/unpoly"
|
28
|
+
|
29
|
+
class App < Sinatra::Base
|
30
|
+
register Sinatra::Unpoly
|
31
|
+
|
32
|
+
get "/" do
|
33
|
+
if up?
|
34
|
+
"Unpoly request!"
|
35
|
+
else
|
36
|
+
"Not Unpoly :("
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
## Usage in a Roda application
|
43
|
+
|
44
|
+
Use the [roda-unpoly](https://rubygems.org/gems/roda-unpoly) gem.
|
45
|
+
|
46
|
+
## Usage in a Rack application (that's not Rails, Sinatra, or Roda)
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require "rack"
|
50
|
+
require "rack/unpoly/middleware"
|
51
|
+
|
52
|
+
use Rack::Unpoly::Middleware
|
53
|
+
|
54
|
+
run ->(env) { [200, {}, ["Hello World"]] }
|
55
|
+
```
|
56
|
+
|
57
|
+
## Where are the Javascript and CSS assets?
|
58
|
+
|
59
|
+
I've chosen not to bundle those assets with the gem as they might be updated more
|
60
|
+
frequently then this library. Most Ruby web libraries outside of Rails are asset-agnostic
|
61
|
+
(for the most part), so it's easier if you bring in your assets as you see fit for your
|
62
|
+
specific needs.
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/adam12/rack-unpoly.
|
67
|
+
|
68
|
+
I love pull requests! If you fork this project and modify it, please ping me to see
|
69
|
+
if your changes can be incorporated back into this project.
|
70
|
+
|
71
|
+
That said, if your feature idea is nontrivial, you should probably open an issue to
|
72
|
+
[discuss it](http://www.igvita.com/2011/12/19/dont-push-your-pull-requests/)
|
73
|
+
before attempting a pull request.
|
74
|
+
|
75
|
+
## License
|
76
|
+
|
77
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "rake/testtask"
|
2
|
+
require "rdoc/task"
|
3
|
+
require "rubygems/tasks"
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << "test"
|
7
|
+
t.test_files = FileList["test/test*.rb"]
|
8
|
+
t.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
RDoc::Task.new do |rdoc|
|
12
|
+
rdoc.main = "README.md"
|
13
|
+
rdoc.rdoc_files.include("README.md", "lib/**/*.rb")
|
14
|
+
end
|
15
|
+
|
16
|
+
Gem::Tasks.new
|
17
|
+
|
18
|
+
task default: :test
|
data/lib/rack/unpoly.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
require "forwardable"
|
3
|
+
|
4
|
+
module Rack # :nodoc:
|
5
|
+
module Unpoly # :nodoc:
|
6
|
+
# Easily inspect the Unpoly environment of the current request.
|
7
|
+
# Inspectors are not normally instantiated by users, but accessed
|
8
|
+
# through +env["rack.unpoly"]+ or one of the convenience wrappers
|
9
|
+
# for Roda and Sinatra.
|
10
|
+
class Inspector
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
def_delegators :request, :get_header # :nodoc:
|
14
|
+
|
15
|
+
attr_reader :request # :nodoc:
|
16
|
+
|
17
|
+
def initialize(request) # :nodoc:
|
18
|
+
@request = request
|
19
|
+
end
|
20
|
+
|
21
|
+
# Determine if this is an Unpoly request.
|
22
|
+
def unpoly?
|
23
|
+
target.to_s.strip != ""
|
24
|
+
end
|
25
|
+
alias up? unpoly?
|
26
|
+
|
27
|
+
# Identify if the +tested_target+ will match the actual target requested.
|
28
|
+
def target?(tested_target)
|
29
|
+
query_target(target, tested_target)
|
30
|
+
end
|
31
|
+
|
32
|
+
# The actual target as requested by Unpoly.
|
33
|
+
def target
|
34
|
+
get_header("HTTP_X_UP_TARGET")
|
35
|
+
end
|
36
|
+
|
37
|
+
# The CSS selector for the fragment Unpoly will update if the request fails.
|
38
|
+
# Requires Unpoly >= 0.50
|
39
|
+
def fail_target
|
40
|
+
get_header("HTTP_X_UP_FAIL_TARGET")
|
41
|
+
end
|
42
|
+
|
43
|
+
# Determine if the provided target is the current target for a failed request.
|
44
|
+
# Requires Unpoly >= 0.50
|
45
|
+
def fail_target?(tested_target)
|
46
|
+
query_target(fail_target, tested_target)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Determine if the provided target is the current target for a successful or failed request.
|
50
|
+
def any_target?(tested_target)
|
51
|
+
target?(tested_target) || fail_target?(tested_target)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Set the page title.
|
55
|
+
def set_title(response, new_title)
|
56
|
+
response.headers["X-Up-Title"] = new_title
|
57
|
+
end
|
58
|
+
|
59
|
+
# Determine if this is a validate request.
|
60
|
+
def validate?
|
61
|
+
validate_name.to_s.strip != ""
|
62
|
+
end
|
63
|
+
|
64
|
+
# The name attribute of the form field that triggered
|
65
|
+
# the validation.
|
66
|
+
def validate_name
|
67
|
+
get_header("HTTP_X_UP_VALIDATE")
|
68
|
+
end
|
69
|
+
|
70
|
+
def query_target(actual_target, tested_target) # :nodoc:
|
71
|
+
if up?
|
72
|
+
if actual_target == tested_target
|
73
|
+
true
|
74
|
+
elsif actual_target == "html"
|
75
|
+
true
|
76
|
+
elsif actual_target == "body"
|
77
|
+
!%w(head title meta).include?(tested_target)
|
78
|
+
else
|
79
|
+
false
|
80
|
+
end
|
81
|
+
else
|
82
|
+
true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
require_relative "inspector"
|
3
|
+
|
4
|
+
module Rack # :nodoc:
|
5
|
+
module Unpoly
|
6
|
+
# Rack Middleware that implements the server protocol expected by Unpoly,
|
7
|
+
# and provides an entry point into the Rack::Unpoly::Inspector for the current
|
8
|
+
# request.
|
9
|
+
#
|
10
|
+
# = Accessing the Rack::Unpoly::Inspector
|
11
|
+
#
|
12
|
+
# An inspector for the current request is available inside +env["rack.unpoly"]+.
|
13
|
+
# You can access any of the inspector methods through this env variable.
|
14
|
+
#
|
15
|
+
# env["rack.unpoly"].up?
|
16
|
+
#
|
17
|
+
# = Middleware Usage Example
|
18
|
+
#
|
19
|
+
# require "rack"
|
20
|
+
# require "rack/unpoly/middleware"
|
21
|
+
#
|
22
|
+
# use Rack::Unpoly::Middleware
|
23
|
+
#
|
24
|
+
# run ->(env) { [200, {}, ["Hello World"]] }
|
25
|
+
class Middleware
|
26
|
+
def initialize(app) # :nodoc:
|
27
|
+
@app = app
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env) # :nodoc:
|
31
|
+
request = Rack::Request.new(env)
|
32
|
+
env["rack.unpoly"] = Inspector.new(request)
|
33
|
+
|
34
|
+
status, headers, response = @app.call(env)
|
35
|
+
setup_protocol(request, headers)
|
36
|
+
|
37
|
+
[status, headers, response]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Implement the *Unpoly* server protocol.
|
43
|
+
# Used internally by the middleware. Not required for normal use.
|
44
|
+
def setup_protocol(request, headers)
|
45
|
+
headers["X-Up-Location"] = request.url
|
46
|
+
headers["X-Up-Method"] = request.request_method
|
47
|
+
|
48
|
+
if !request.get? && !request.env["rack.unpoly"].unpoly?
|
49
|
+
Rack::Utils.set_cookie_header!(headers, "_up_method",
|
50
|
+
{ value: request.request_method, path: "/" })
|
51
|
+
else
|
52
|
+
Rack::Utils.delete_cookie_header!(headers, "_up_method", { path: "/" })
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
require "rack/unpoly/middleware"
|
3
|
+
require "delegate"
|
4
|
+
|
5
|
+
module Sinatra # :nodoc:
|
6
|
+
# The Unpoly extension for Sinatra provides a little bit of sugar to make
|
7
|
+
# Unpoly work seamlessly with Roda.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# = Example
|
11
|
+
#
|
12
|
+
# require "sinatra/base"
|
13
|
+
# require "sinatra/unpoly"
|
14
|
+
#
|
15
|
+
# class App < Sinatra::Base
|
16
|
+
# register Sinatra::Unpoly
|
17
|
+
#
|
18
|
+
# get "/" do
|
19
|
+
# if up?
|
20
|
+
# "Unpoly request!"
|
21
|
+
# else
|
22
|
+
# "Not Unpoly :("
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
module Unpoly
|
28
|
+
class SinatraInspector < DelegateClass(Rack::Unpoly::Inspector)
|
29
|
+
attr_accessor :response # :nodoc:
|
30
|
+
|
31
|
+
def initialize(obj, response) # :nodoc:
|
32
|
+
super(obj)
|
33
|
+
@response = response
|
34
|
+
end
|
35
|
+
|
36
|
+
# Set the page title.
|
37
|
+
def title=(value)
|
38
|
+
set_title(response, value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Helpers
|
43
|
+
# The ::Rack::Unpoly inspector for this request.
|
44
|
+
def unpoly
|
45
|
+
SinatraInspector.new(env["rack.unpoly"], response)
|
46
|
+
end
|
47
|
+
alias up unpoly
|
48
|
+
|
49
|
+
# Determine if this is an Unpoly request.
|
50
|
+
def unpoly?
|
51
|
+
unpoly.unpoly?
|
52
|
+
end
|
53
|
+
alias up? unpoly?
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.registered(app) # :nodoc:
|
57
|
+
app.use Rack::Unpoly::Middleware
|
58
|
+
app.helpers Unpoly::Helpers
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-unpoly
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Daniels
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: minitest
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '5.0'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '5.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rubygems-tasks
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.2'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0.2'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rack-test
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.6'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0.6'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: sinatra
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '2.0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '2.0'
|
103
|
+
description:
|
104
|
+
email: adam@mediadrive.ca
|
105
|
+
executables: []
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files: []
|
108
|
+
files:
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- lib/rack/unpoly.rb
|
112
|
+
- lib/rack/unpoly/inspector.rb
|
113
|
+
- lib/rack/unpoly/middleware.rb
|
114
|
+
- lib/sinatra/unpoly.rb
|
115
|
+
homepage: https://github.com/adam12/rack-unpoly
|
116
|
+
licenses:
|
117
|
+
- MIT
|
118
|
+
metadata: {}
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubyforge_project:
|
135
|
+
rubygems_version: 2.6.13
|
136
|
+
signing_key:
|
137
|
+
specification_version: 4
|
138
|
+
summary: Integrate Unpoly with any Rack or Sinatra application
|
139
|
+
test_files: []
|