rack-unpoly 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|