rack-param_to_cookie 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 36aaf45de3d68dad838f4ef7c340316756698f6e
4
+ data.tar.gz: 01ff0729c13a30a8f8497ffa92ba83d8d9b5b259
5
+ SHA512:
6
+ metadata.gz: e9d73307405f7344505f783fd77fe1f05ed801c73f4d24686a147ca3f8501f523eea3744be58611c35c988e0308d9e78dc941049755c69ce8a965742507d3eff
7
+ data.tar.gz: d059d64e866b4d6cea3538f6229091252936d5073f32e3c02dd28a459ff004ae02a2b390c88cf851592ea928009064b4ef159db01a1f61d9ec819fd8f92ce237
data/README.rdoc ADDED
@@ -0,0 +1,74 @@
1
+ = Rack::ParamToCookie
2
+
3
+ * https://github.com/jdleesmiller/rack-param_to_cookie
4
+
5
+ == SYNOPSIS
6
+
7
+ Rack::ParamToCookie is a rack middleware that extracts request parameters from requests and stores them in cookies for use in future requests. It's useful for affiliate, referral or promotion links, which often work something like:
8
+
9
+ 1. A referral partner puts a link on their site to somewhere on your site, and they include a request parameter like +ref+ so you can identify traffic from them, e.g. https://www.example.com/some-interesting-page?ref=123ABC
10
+ 1. A user clicks through the link and comes to your site.
11
+ 1. The Rack::ParamToCookie middleware finds the +ref+ parameter and stores it in a cookie for this user.
12
+ 1. The user browses around for a while and eventually signs up.
13
+ 1. Your sign up action recovers the referral code, +123ABC+, from the cookie, and you mark it as a successful referral from your partner.
14
+ 1. $$$$!
15
+
16
+ == Usage
17
+
18
+ In a Rails app, you can add it as middleware in +config/application.rb+. For a parameter called +ref+, the basic usage is:
19
+
20
+ config.middleware.use 'Rack::ParamToCookie', 'ref' => {}
21
+
22
+ This tells Rack::ParamToCookie to capture a request parameter called +ref+, store it in a cookie called +ref+, and make it available in your rails app as <tt>request.env['ref']</tt>. You can specify multiple parameters and configure them. Here's a more in-depth example:
23
+
24
+ config.middleware.use 'Rack::ParamToCookie',
25
+ 'ref' => {cookie_name: 'referral_code',
26
+ env_name: 'referral.code',
27
+ ttl: 14*24*60*60},
28
+ 'aff' => {cookie_name: 'affiliate_code',
29
+ env_name: 'affiliate.code'}
30
+
31
+ The first cookie, +referral_code+ for parameter +ref+, has a 14 day time to live and is accessible in +request.env+ <tt>['referral.code']</tt>. The second, for parameter +aff+, has the default time to live, which is 30 days.
32
+
33
+ == Installation
34
+
35
+ Add to your Gemfile
36
+
37
+ gem 'rack-param_to_cookie'
38
+
39
+ Or install directly
40
+
41
+ gem install rack-param_to_cookie
42
+
43
+ You can load it with
44
+
45
+ require 'rack/param_to_cookie'
46
+
47
+ == Credits
48
+
49
+ This middleware is mostly based on Rack::Affiliates (https://github.com/alexlevin/rack-affiliates); this middleware is just a bit more generic and configurable.
50
+
51
+ == License
52
+
53
+ (The MIT License)
54
+
55
+ Copyright (c) 2014 John Lees-Miller
56
+
57
+ Permission is hereby granted, free of charge, to any person obtaining
58
+ a copy of this software and associated documentation files (the
59
+ 'Software'), to deal in the Software without restriction, including
60
+ without limitation the rights to use, copy, modify, merge, publish,
61
+ distribute, sublicense, and/or sell copies of the Software, and to
62
+ permit persons to whom the Software is furnished to do so, subject to
63
+ the following conditions:
64
+
65
+ The above copyright notice and this permission notice shall be
66
+ included in all copies or substantial portions of the Software.
67
+
68
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
69
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
70
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
71
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
72
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
73
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
74
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ require 'rack/param_to_cookie'
@@ -0,0 +1,58 @@
1
+ require 'rack/param_to_cookie/version'
2
+
3
+ module Rack
4
+ #
5
+ # Rack middleware. See README.
6
+ #
7
+ class ParamToCookie
8
+ #
9
+ # @param [Object] app
10
+ #
11
+ # @param [Hash<String, Hash>] param_cookies map from parameter names to
12
+ # cookie options
13
+ #
14
+ def initialize app, param_cookies
15
+ @app = app
16
+ @param_cookies = param_cookies
17
+ @param_cookies.each do |param, options|
18
+ options[:cookie_name] ||= param
19
+ options[:env_name] ||= param
20
+ options[:ttl] ||= 60*60*24*30 # 30 days
21
+ options[:set_cookie_options] ||= {}
22
+ end
23
+ end
24
+
25
+ def call env
26
+ req = Rack::Request.new(env)
27
+
28
+ updated_cookies = {}
29
+ @param_cookies.each do |param, options|
30
+ # get the value from a previously set cookie
31
+ cookie_value = req.cookies[options[:cookie_name]]
32
+
33
+ # check whether there's a new value for the cookie with this request
34
+ params_value = req.params[param] rescue nil
35
+
36
+ value = params_value || cookie_value
37
+ env[options[:env_name]] = value if value
38
+
39
+ # once we handle the response, set the new cookie value
40
+ if params_value
41
+ updated_cookies[options[:cookie_name]] =
42
+ options[:set_cookie_options].merge(
43
+ value: params_value,
44
+ expires: Time.now + options[:ttl])
45
+ end
46
+ end
47
+
48
+ status, headers, body = @app.call(env)
49
+ response = Rack::Response.new body, status, headers
50
+
51
+ updated_cookies.each do |cookie, options|
52
+ response.set_cookie cookie, options
53
+ end
54
+
55
+ response.finish
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,8 @@
1
+ module Rack
2
+ class ParamToCookie
3
+ VERSION_MAJOR = 1
4
+ VERSION_MINOR = 0
5
+ VERSION_PATCH = 0
6
+ VERSION = [VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH].join('.')
7
+ end
8
+ end
@@ -0,0 +1,135 @@
1
+ require 'minitest/autorun'
2
+ require 'rack/test'
3
+
4
+ require 'rack/param_to_cookie'
5
+
6
+ describe "Rack::ParamToCookie" do
7
+ include Rack::Test::Methods
8
+
9
+ def make_app *param_cookies
10
+ dummy_app = lambda do |env|
11
+ [200, {'Content-Type' => 'text/plain'}, ['hi']]
12
+ end
13
+ @app = Rack::ParamToCookie.new(dummy_app, *param_cookies)
14
+ end
15
+
16
+ def app
17
+ @app
18
+ end
19
+
20
+ describe "with defaults and a ref param" do
21
+ before do
22
+ make_app 'ref' => {}
23
+ clear_cookies
24
+ end
25
+
26
+ it "should do nothing when there is no ref parameter" do
27
+ get '/'
28
+
29
+ assert_equal nil, last_request.env['ref']
30
+ assert_equal({}, rack_mock_session.cookie_jar.to_hash)
31
+ end
32
+
33
+ it "should set a ref cookie if one is present" do
34
+ # first request sets ref
35
+ get '/', ref: 'abc'
36
+ assert_equal 'abc', last_request.env['ref']
37
+ assert_equal({'ref' => 'abc'}, rack_mock_session.cookie_jar.to_hash)
38
+ assert_match(/abc/, last_response.headers['Set-Cookie'])
39
+
40
+ # it should be remembered on the second request
41
+ get '/'
42
+ assert_equal 'abc', last_request.env['ref']
43
+ assert_equal({'ref' => 'abc'}, rack_mock_session.cookie_jar.to_hash)
44
+ assert_equal nil, last_response.headers['Set-Cookie']
45
+
46
+ # if we set it again, it gets overwritten
47
+ get '/', ref: '123'
48
+ assert_equal '123', last_request.env['ref']
49
+ assert_equal({'ref' => '123'}, rack_mock_session.cookie_jar.to_hash)
50
+ assert_match(/123/, last_response.headers['Set-Cookie'])
51
+
52
+ # ... and remembered
53
+ get '/'
54
+ assert_equal '123', last_request.env['ref']
55
+ assert_equal({'ref' => '123'}, rack_mock_session.cookie_jar.to_hash)
56
+ assert_equal nil, last_response.headers['Set-Cookie']
57
+ end
58
+ end
59
+
60
+ describe "with multiple parameters and custom names" do
61
+ before do
62
+ make_app \
63
+ 'ref' => {cookie_name: 'ref_cookie', env_name: 'ref.env', ttl: 10},
64
+ 'aff' => {cookie_name: 'aff_cookie', env_name: 'aff.env', ttl: 20}
65
+ clear_cookies
66
+ end
67
+
68
+ it "should set ref and aff" do
69
+ # initially no cookies
70
+ get '/'
71
+ assert_equal nil, last_request.env['ref.env']
72
+ assert_equal nil, last_request.env['aff.env']
73
+ assert_equal({}, rack_mock_session.cookie_jar.to_hash)
74
+
75
+ # set both at the same time
76
+ get '/', ref: 'foo', aff: 'bar'
77
+ assert_equal 'foo', last_request.env['ref.env']
78
+ assert_equal 'bar', last_request.env['aff.env']
79
+ assert_equal({'ref_cookie' => 'foo', 'aff_cookie' => 'bar'},
80
+ rack_mock_session.cookie_jar.to_hash)
81
+
82
+ # should have set cookies with expiry times ~10s and ~20s, resp.
83
+ cookie_header = last_response.headers['Set-Cookie']
84
+ expires = cookie_header.scan(/^(.+?)_cookie=.+?; expires=(.+?)$/)
85
+ expires = expires.map {|cookie, date| [cookie, Time.parse(date)]}.to_h
86
+ assert expires['ref'] > Time.now + 9
87
+ assert expires['ref'] <= Time.now + 11
88
+ assert expires['aff'] > Time.now + 19
89
+ assert expires['aff'] <= Time.now + 21
90
+ assert_equal 2, expires.size
91
+
92
+ # retreive both
93
+ get '/'
94
+ assert_equal 'foo', last_request.env['ref.env']
95
+ assert_equal 'bar', last_request.env['aff.env']
96
+ assert_equal({'ref_cookie' => 'foo', 'aff_cookie' => 'bar'},
97
+ rack_mock_session.cookie_jar.to_hash)
98
+ assert_equal nil, last_response.headers['Set-Cookie']
99
+
100
+ # update ref
101
+ get '/', ref: 'baz'
102
+ assert_equal 'baz', last_request.env['ref.env']
103
+ assert_equal 'bar', last_request.env['aff.env']
104
+ assert_equal({'ref_cookie' => 'baz', 'aff_cookie' => 'bar'},
105
+ rack_mock_session.cookie_jar.to_hash)
106
+ assert_match(/baz/, last_response.headers['Set-Cookie'])
107
+ assert(/bar/ !~ last_response.headers['Set-Cookie'])
108
+
109
+ # retreive both
110
+ get '/'
111
+ assert_equal 'baz', last_request.env['ref.env']
112
+ assert_equal 'bar', last_request.env['aff.env']
113
+ assert_equal({'ref_cookie' => 'baz', 'aff_cookie' => 'bar'},
114
+ rack_mock_session.cookie_jar.to_hash)
115
+ assert_equal nil, last_response.headers['Set-Cookie']
116
+
117
+ # update aff
118
+ get '/', aff: 'bat'
119
+ assert_equal 'baz', last_request.env['ref.env']
120
+ assert_equal 'bat', last_request.env['aff.env']
121
+ assert_equal({'ref_cookie' => 'baz', 'aff_cookie' => 'bat'},
122
+ rack_mock_session.cookie_jar.to_hash)
123
+ assert_match(/bat/, last_response.headers['Set-Cookie'])
124
+ assert(/baz/ !~ last_response.headers['Set-Cookie'])
125
+
126
+ # retreive both
127
+ get '/'
128
+ assert_equal 'baz', last_request.env['ref.env']
129
+ assert_equal 'bat', last_request.env['aff.env']
130
+ assert_equal({'ref_cookie' => 'baz', 'aff_cookie' => 'bat'},
131
+ rack_mock_session.cookie_jar.to_hash)
132
+ assert_equal nil, last_response.headers['Set-Cookie']
133
+ end
134
+ end
135
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-param_to_cookie
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - John Lees-Miller
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-11 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: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gemma
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 4.1.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 4.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Store selected request parameters to cookies for use in future requests.
56
+ Useful for affiliate, referral or promotion links.
57
+ email:
58
+ - jdleesmiller@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files:
62
+ - README.rdoc
63
+ files:
64
+ - README.rdoc
65
+ - lib/rack-param_to_cookie.rb
66
+ - lib/rack/param_to_cookie.rb
67
+ - lib/rack/param_to_cookie/version.rb
68
+ - test/rack/param_to_cookie/param_to_cookie_test.rb
69
+ homepage: https://github.com/jdleesmiller/rack-param_to_cookie
70
+ licenses: []
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options:
74
+ - "--main"
75
+ - README.rdoc
76
+ - "--title"
77
+ - rack-param_to_cookie-1.0.0 Documentation
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.2.2
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Store selected request parameters to cookies.
96
+ test_files:
97
+ - test/rack/param_to_cookie/param_to_cookie_test.rb
98
+ has_rdoc: