diversion 0.0.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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +193 -0
- data/Rakefile +7 -0
- data/diversion.gemspec +40 -0
- data/lib/diversion.rb +35 -0
- data/lib/diversion/client.rb +21 -0
- data/lib/diversion/configurable.rb +100 -0
- data/lib/diversion/decode.rb +21 -0
- data/lib/diversion/decode/json.rb +47 -0
- data/lib/diversion/decode/params.rb +55 -0
- data/lib/diversion/encode.rb +67 -0
- data/lib/diversion/encode/json.rb +31 -0
- data/lib/diversion/encode/params.rb +26 -0
- data/lib/diversion/error.rb +2 -0
- data/lib/diversion/error/bad_url_data_format.rb +6 -0
- data/lib/diversion/error/configuration_error.rb +6 -0
- data/lib/diversion/error/key_missing_error.rb +6 -0
- data/lib/diversion/error/uri_missing_error.rb +6 -0
- data/lib/diversion/mailer.rb +11 -0
- data/lib/diversion/signing.rb +19 -0
- data/lib/diversion/url.rb +43 -0
- data/lib/diversion/version.rb +17 -0
- data/spec/coverage/assets/0.7.1/application.css +1110 -0
- data/spec/coverage/assets/0.7.1/application.js +626 -0
- data/spec/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
- data/spec/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
- data/spec/coverage/assets/0.7.1/favicon_green.png +0 -0
- data/spec/coverage/assets/0.7.1/favicon_red.png +0 -0
- data/spec/coverage/assets/0.7.1/favicon_yellow.png +0 -0
- data/spec/coverage/assets/0.7.1/loading.gif +0 -0
- data/spec/coverage/assets/0.7.1/magnify.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/spec/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/spec/coverage/index.html +3146 -0
- data/spec/diversion/client_spec.rb +23 -0
- data/spec/diversion/configurable_spec.rb +128 -0
- data/spec/diversion/decode/json_decode_spec.rb +70 -0
- data/spec/diversion/decode/params_decode_spec.rb +74 -0
- data/spec/diversion/decode_spec.rb +12 -0
- data/spec/diversion/encode/json_encode_spec.rb +39 -0
- data/spec/diversion/encode/params_encode_spec.rb +39 -0
- data/spec/diversion/encode_spec.rb +30 -0
- data/spec/diversion/mailer_spec.rb +31 -0
- data/spec/diversion/support/global_shared_context.rb +29 -0
- data/spec/diversion/url_spec.rb +36 -0
- data/spec/fixtures/mail.html +13 -0
- data/spec/fixtures/sample_email.multipart +39 -0
- data/spec/fixtures/sample_email.text +12 -0
- data/spec/spec_helper.rb +84 -0
- metadata +323 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: e1d9abf9fb297a4097cb0d52b23e802b1df837a2
|
|
4
|
+
data.tar.gz: 6aaa3057c3e72b0a835a84828375c8a057d9976c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ad2b860ce09fe117ec736c249fdce3809fec2d3d42ae98c28090a684e84dbda60f3d16f3124292626d7534cde33f116a5fdbc95c721fe0b0fbf8c888d6ad7589
|
|
7
|
+
data.tar.gz: 5c68a4ce1c9488aab7c2a6a1c1677a9ceabc84287e6764f3c0333a36ff3785b24e5e84a71b0f238819da4bbc8acf8ea6b1ab07175d0b599d0181ac0b56a0a2da
|
checksums.yaml.gz.sig
ADDED
|
Binary file
|
data.tar.gz.sig
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 Richard Hollis
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Diversion Ruby Gem
|
|
2
|
+
|
|
3
|
+
[][gem]
|
|
4
|
+
[][travis]
|
|
5
|
+
[][gemnasium]
|
|
6
|
+
[][coveralls]
|
|
7
|
+
|
|
8
|
+
[gem]: https://rubygems.org/gems/diversion
|
|
9
|
+
[travis]: http://travis-ci.org/richhollis/diversion
|
|
10
|
+
[gemnasium]: https://gemnasium.com/richhollis/diversion
|
|
11
|
+
[coveralls]: https://coveralls.io/r/richhollis/diversion
|
|
12
|
+
|
|
13
|
+
Redirect HTML links through your preferred redirection URL
|
|
14
|
+
|
|
15
|
+
Diversion aims are simple - to be a framework agnostic way to redirect all URLs via another path whilst leaving the original URL intact, leaving you to perform the actual implementation of the redirection logic.
|
|
16
|
+
|
|
17
|
+
Link redirection is particularly desirable for some Rails mailers where you want to track a link click first before redirecting the user to the original link.
|
|
18
|
+
|
|
19
|
+
Diversion was created specifically with a Rails use case in mind but can be used without Rails/ActionMailer.
|
|
20
|
+
|
|
21
|
+
A Rails mailer helper is provided if you are using ActionMailer.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
gem install diversion
|
|
26
|
+
|
|
27
|
+
To ensure the code you're installing hasn't been tampered with, it's recommended that you verify the signature. To do this, you need to add my public key as a trusted certificate (you only need to do this once):
|
|
28
|
+
|
|
29
|
+
gem cert --add <(curl -Ls https://gist.github.com/richhollis/5301656/raw/richhollis.pem)
|
|
30
|
+
|
|
31
|
+
Then, install the gem with the high security trust policy:
|
|
32
|
+
|
|
33
|
+
gem install twitter -P HighSecurity
|
|
34
|
+
|
|
35
|
+
Add this line to your application's Gemfile:
|
|
36
|
+
|
|
37
|
+
gem 'diversion'
|
|
38
|
+
|
|
39
|
+
And then execute:
|
|
40
|
+
|
|
41
|
+
$ bundle
|
|
42
|
+
|
|
43
|
+
Or install it yourself as:
|
|
44
|
+
|
|
45
|
+
$ gem install diversion
|
|
46
|
+
|
|
47
|
+
## Quick Start Guide & Example
|
|
48
|
+
|
|
49
|
+
Configure your redirection settings:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
Diversion.configure do |config|
|
|
53
|
+
config.host = 'http://localhost.domain'
|
|
54
|
+
config.path = '/redirect/'
|
|
55
|
+
end
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Example usage:
|
|
59
|
+
|
|
60
|
+
Encode takes an HTML body and encodes all anchor links to the new redirection location.
|
|
61
|
+
|
|
62
|
+
You can specifiy additional parameters for each url by using a "data-" attribute, for example:
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<a data-from="welcome_email" href="http://www.youtube.com/watch?v=feeA-Dr0XGw">Portlandia Intro</a>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The data-from attribute will be added to the encoded parameters and will be available when the URL is decoded.
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
Diversion::encode('<a data-from="welcome_email" href="http://www.youtube.com/watch?v=feeA-Dr0XGw">Portlandia Intro</a>')
|
|
72
|
+
# => "<a href=\"http://localhost.domain/redirect/1/?d=from%3Dwelcome_email%26url%3Dhttp%253A%252F%252Fwww.youtube.com%252Fwatch%253Fv%253DfeeA-Dr0XGw\">Portlandia Intro</a>"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Then to get the original data (this might be in say your Redirect controller) we parse the parameters of the URL:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
Diversion::decode('d=from%3Dwelcome_email%26url%3Dhttp%253A%252F%252Fwww.youtube.com%252Fwatch%253Fv%253DfeeA-Dr0XGw')
|
|
79
|
+
# => {:key_presented=>"", :parsed=>true, :signed=>false, :key_expected=>"", :key_verified=>false, :from=>"welcome_email", :url=>"http://www.youtube.com/watch?v=feeA-Dr0XGw"}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Global data parameters
|
|
83
|
+
|
|
84
|
+
You can specify parameters that should be present for all encoded URLs. This might typically be an ID or something similar.
|
|
85
|
+
Specify these parameters in the second parameter to the encode (or diversion mailer) method with a hash of the parameters you wish to add.
|
|
86
|
+
|
|
87
|
+
Example:
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
Diversion::encode('<a data-from="welcome_email" href="http://www.youtube.com/watch?v=feeA-Dr0XGw">Portlandia Intro</a>', {:id => 1} )
|
|
91
|
+
# => => "<a href=\"http://localhost.domain/redirect/1/?d=from%3Dwelcome_email%26id%3D1%26url%3Dhttp%253A%252F%252Fwww.youtube.com%252Fwatch%253Fv%253DfeeA-Dr0XGw\">Portlandia Intro</a>"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Overriding configuration parameters
|
|
95
|
+
|
|
96
|
+
You can the global configuration by specifying a third parameter to encode (or diversion mailer) with a hash of the parameters you wish to override.
|
|
97
|
+
|
|
98
|
+
Example:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
Diversion::encode('<a data-from="welcome_email" href="http://www.youtube.com/watch?v=feeA-Dr0XGw">Portlandia Intro</a>', {:id => 1}, {:encode_uris => ['https']} )
|
|
102
|
+
# => "<a data-from=\"welcome_email\" href=\"http://www.youtube.com/watch?v=feeA-Dr0XGw\">Portlandia Intro</a>"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Note: Because we've overridden the encode_uris setting to only encode https urls our URL hasn't been redirected.
|
|
106
|
+
|
|
107
|
+
## Enabling Url 'Signing'
|
|
108
|
+
|
|
109
|
+
You can 'sign' the url which works by appending a parameter with a hash of the URL. The hash can be as long as 32 characters. When you enable signing, but setting the sign_length configuration option you can choose between 0-32, where 0 is disabled. The hash is generated using HMAC::MD5.
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
Diversion.configure do |config|
|
|
113
|
+
config.sign_length = 2
|
|
114
|
+
config.sign_key = 'yoursecretkey'
|
|
115
|
+
end
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Changing the Encoding Method
|
|
119
|
+
|
|
120
|
+
The default encoding method is query string parameters (Encode::Params/Decode::Params). This can be changed for JSON if you wish (Encode::Json/Decode::Json).
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
Diversion.configure do |config|
|
|
124
|
+
config.url_encoding = Encode::Json
|
|
125
|
+
config.url_decoding = Decode::Json
|
|
126
|
+
end
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Rails Mailer Example
|
|
130
|
+
|
|
131
|
+
app/views/test_mailer/welcome_email.html.erb:
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<p>Hey</p>
|
|
135
|
+
|
|
136
|
+
<p>Click on the following link to view some great content:</p>
|
|
137
|
+
|
|
138
|
+
<a data-type="video" href="http://www.youtube.com/watch?v=feeA-Dr0XGw">Portlandia</a>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
app/mailers/test_mailer.rb:
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
class TestMailer < ActionMailer::Base
|
|
145
|
+
default from: "from@example.com"
|
|
146
|
+
|
|
147
|
+
def welcome_email
|
|
148
|
+
# Note: we're adding a global parameter user_id - this is optional
|
|
149
|
+
mail(:to => 'somebody@no.where', :subject => "Welcome to My Awesome Site").diversion({:user_id => 1})
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Note: Remember you can also add global parameters and override config options buy passing these to the diversion helper too - e.g.
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
mail(:to => 'somebody@no.where', :subject => "Welcome to My Awesome Site").diversion({:user_id => 1}, {:encode_uris => ['http']} )
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
app/controllers/redirect_controller.rb:
|
|
161
|
+
|
|
162
|
+
```ruby
|
|
163
|
+
class RedirectController < ApplicationController
|
|
164
|
+
|
|
165
|
+
respond_to :html
|
|
166
|
+
|
|
167
|
+
def show
|
|
168
|
+
hash = Diversion::decode(request.query_string)
|
|
169
|
+
|
|
170
|
+
# do something with parameters hash like save request in database
|
|
171
|
+
|
|
172
|
+
# output parameters
|
|
173
|
+
render :text => hash
|
|
174
|
+
|
|
175
|
+
# or redirect
|
|
176
|
+
# redirect_to(hash[:url])
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Sample Redirect Controller output:
|
|
183
|
+
|
|
184
|
+
{:key_presented=>"", :parsed=>true, :signed=>false, :key_expected=>"", :key_verified=>false, :from=>"welcome_email", :url=>"http://www.youtube.com/watch?v=feeA-Dr0XGw", :user_id => 1}
|
|
185
|
+
|
|
186
|
+
## Contributing
|
|
187
|
+
|
|
188
|
+
1. Fork it
|
|
189
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
190
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
191
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
192
|
+
5. Provide tests for the changes
|
|
193
|
+
6. Create new Pull Request
|
data/Rakefile
ADDED
data/diversion.gemspec
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'diversion/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |gem|
|
|
7
|
+
gem.name = "diversion"
|
|
8
|
+
gem.version = Diversion::Version
|
|
9
|
+
gem.authors = ["Richard Hollis"]
|
|
10
|
+
gem.email = ["richhollis@gmail.com"]
|
|
11
|
+
gem.description = %q{Redirect HTML links through your preferred redirection URL}
|
|
12
|
+
gem.summary = gem.description
|
|
13
|
+
gem.homepage = "https://github.com/richhollis/diversion/"
|
|
14
|
+
|
|
15
|
+
gem.cert_chain = ['certs/richhollis.pem']
|
|
16
|
+
gem.signing_key = File.expand_path("~/.gem/private_key.pem") if $0 =~ /gem\z/
|
|
17
|
+
|
|
18
|
+
gem.files = %w(LICENSE.txt README.md Rakefile diversion.gemspec)
|
|
19
|
+
gem.files += Dir.glob("lib/**/*.rb")
|
|
20
|
+
gem.files += Dir.glob("spec/**/*")
|
|
21
|
+
|
|
22
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
23
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
24
|
+
gem.require_paths = ["lib"]
|
|
25
|
+
gem.test_files = Dir.glob('spec/**/*')
|
|
26
|
+
|
|
27
|
+
gem.licenses = ['MIT']
|
|
28
|
+
|
|
29
|
+
gem.add_dependency "activesupport", ['>= 3.0', '< 4.1']
|
|
30
|
+
gem.add_dependency "nokogiri"
|
|
31
|
+
gem.add_dependency "ruby-hmac"
|
|
32
|
+
gem.add_dependency 'multi_json', '~> 1.0'
|
|
33
|
+
|
|
34
|
+
gem.add_development_dependency "actionmailer", ['>= 3.0', '< 4.1']
|
|
35
|
+
gem.add_development_dependency "rspec"
|
|
36
|
+
gem.add_development_dependency "simplecov" if RUBY_VERSION >= '1.9'
|
|
37
|
+
gem.add_development_dependency "coveralls"
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
data/lib/diversion.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
if defined?(ActionMailer)
|
|
2
|
+
require 'action_mailer/version'
|
|
3
|
+
require 'diversion/mailer'
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
require "diversion/error"
|
|
7
|
+
require "diversion/client"
|
|
8
|
+
require "diversion/version"
|
|
9
|
+
|
|
10
|
+
module Diversion
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
include Diversion::Configurable
|
|
14
|
+
|
|
15
|
+
# Delegate to a Diversion::Client
|
|
16
|
+
#
|
|
17
|
+
# @return [Diversion::Client]
|
|
18
|
+
def client
|
|
19
|
+
@client = Diversion::Client.new(options) unless defined?(@client) && @client.hash == options.hash
|
|
20
|
+
@client
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def respond_to_missing?(method_name, include_private=false); client.respond_to?(method_name, include_private); end if RUBY_VERSION >= "1.9"
|
|
24
|
+
def respond_to?(method_name, include_private=false); client.respond_to?(method_name, include_private) || super; end if RUBY_VERSION < "1.9"
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def method_missing(method_name, *args, &block)
|
|
29
|
+
return super unless client.respond_to?(method_name)
|
|
30
|
+
client.send(method_name, *args, &block)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Diversion.setup
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'diversion/configurable'
|
|
2
|
+
require 'diversion/encode'
|
|
3
|
+
require 'diversion/decode'
|
|
4
|
+
|
|
5
|
+
module Diversion
|
|
6
|
+
|
|
7
|
+
class Client
|
|
8
|
+
|
|
9
|
+
include Configurable
|
|
10
|
+
include Encode
|
|
11
|
+
include Decode
|
|
12
|
+
|
|
13
|
+
def initialize(options={})
|
|
14
|
+
Diversion::Configurable.keys.each do |key|
|
|
15
|
+
instance_variable_set(:"@#{key}", options[key] || Diversion.instance_variable_get(:"@#{key}"))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
require 'diversion/error/configuration_error'
|
|
3
|
+
|
|
4
|
+
module Diversion
|
|
5
|
+
module Configurable
|
|
6
|
+
extend Forwardable
|
|
7
|
+
attr_accessor :host, :port, :path, :sign_key, :sign_length, :encode_uris
|
|
8
|
+
attr_accessor :url_encoding, :url_decoding
|
|
9
|
+
def_delegator :options, :hash
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
|
|
13
|
+
def keys
|
|
14
|
+
@keys ||= [
|
|
15
|
+
:host,
|
|
16
|
+
:port,
|
|
17
|
+
:path,
|
|
18
|
+
:sign_key,
|
|
19
|
+
:sign_length,
|
|
20
|
+
:encode_uris,
|
|
21
|
+
:url_encoding,
|
|
22
|
+
:url_decoding
|
|
23
|
+
]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def configure
|
|
29
|
+
yield self
|
|
30
|
+
validate_configuration!
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def reset!
|
|
35
|
+
@host = 'http://localhost.domain'
|
|
36
|
+
@port = 80
|
|
37
|
+
@path = '/redirect/1/'
|
|
38
|
+
@sign_length = 0
|
|
39
|
+
@sign_key = nil
|
|
40
|
+
@encode_uris = ['http','https']
|
|
41
|
+
@url_encoding = Encode::Params
|
|
42
|
+
@url_decoding = Decode::Params
|
|
43
|
+
validate_configuration!
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
alias setup reset!
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# @return [Hash]
|
|
51
|
+
def options
|
|
52
|
+
Hash[Diversion::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Ensures that all configuration parameters are of an expected type.
|
|
56
|
+
#
|
|
57
|
+
# @raise [Diversion::Error::ConfigurationError] Error is raised when
|
|
58
|
+
# supplied configuration is not of expected type
|
|
59
|
+
def validate_configuration!
|
|
60
|
+
unless @host.is_a?(String) && @host.length > 0
|
|
61
|
+
raise(Error::ConfigurationError, "Invalid host specified: Host must contain the host to redirect to.")
|
|
62
|
+
end
|
|
63
|
+
if @host.end_with?('/')
|
|
64
|
+
raise(Error::ConfigurationError, "Invalid host specified: #{@host} should not end with a trailing slash.")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
unless @path.is_a?(String) && @path.length > 0
|
|
68
|
+
raise(Error::ConfigurationError, "Invalid path specified: Path must contain a path to redirect to.")
|
|
69
|
+
end
|
|
70
|
+
unless @path.end_with?('/')
|
|
71
|
+
raise(Error::ConfigurationError, "Invalid path specified: #{@path} should end with a trailing slash.")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
unless @port.is_a?(Integer) && @port > 0
|
|
75
|
+
raise(Error::ConfigurationError, "Invalid port specified: #{@port} must be an integer and non-zero.")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if !@sign_key.nil? && !@sign_key.is_a?(String)
|
|
79
|
+
raise(Error::ConfigurationError, "Invalid sign_key specified: #{@sign_key} must be a String.")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
unless @sign_length.is_a?(Integer) && @sign_length.between?(0, Signing::MAX_SIGN_LENGTH)
|
|
83
|
+
raise(Error::ConfigurationError, "Invalid sign_length specified: #{@sign_length} must be an integer between 0-#{Signing::MAX_SIGN_LENGTH}.")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
unless @encode_uris.is_a?(Array) && @encode_uris.count > 0
|
|
87
|
+
raise(Error::ConfigurationError, "Invalid encode_uris specified: #{@encode_uris} must be an array with at least one URI scheme.")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
unless @url_encoding.is_a?(Module) && Encode::ENCODERS.include?(@url_encoding)
|
|
91
|
+
raise(Error::ConfigurationError, "Invalid url_encoding specified: #{@url_encoding} must be a valid encoder module.")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
unless @url_decoding.is_a?(Module) && Decode::DECODERS.include?(@url_decoding)
|
|
95
|
+
raise(Error::ConfigurationError, "Invalid url_decoding specified: #{@url_decoding} must be a valid decoder module.")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'diversion/decode/json'
|
|
2
|
+
require 'diversion/decode/params'
|
|
3
|
+
|
|
4
|
+
module Diversion
|
|
5
|
+
module Decode
|
|
6
|
+
include Base64
|
|
7
|
+
include Signing
|
|
8
|
+
|
|
9
|
+
DECODERS = [ Params, Json ]
|
|
10
|
+
|
|
11
|
+
def decode(data, opts = {})
|
|
12
|
+
raise ArgumentError if data.length == 0
|
|
13
|
+
|
|
14
|
+
opts = options.merge(opts)
|
|
15
|
+
|
|
16
|
+
# get hash for required type
|
|
17
|
+
hash = opts[:url_decoding].get_hash(data, opts)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|