action-server 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f6d87a00a90000a0eb724de5d25f45d2f3bb0a11
4
+ data.tar.gz: ab538631f2e85a10ebe7dc85f01ea3a2862cc7dc
5
+ SHA512:
6
+ metadata.gz: ac85b0b8e351e0c63a3258fb57cddefe7a814fc788f58f26163e80f922a676fd33c6441fb6055f6dd805e3c974445225bc234866011cc1008bbefa8631ce083c
7
+ data.tar.gz: cbc44b83ce68d61c31f3af73300b78a19c4f7a32248cc754f656e4ca22642352f9ad6312eafc4cf688c99f2ba48c7367f8ed89a03a9fd3cf2b832afb2d9044c6
@@ -0,0 +1,6 @@
1
+ .gitkeep
2
+ .bundle/
3
+ cache/*.cache
4
+ pkg/
5
+ tmp/
6
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in url_encryptor.gemspec
4
+ gemspec
@@ -0,0 +1,85 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ action-server (0.0.1)
5
+ bunny (~> 1.6)
6
+ multi_json (~> 1.10)
7
+ oj (~> 2.10)
8
+ rack (~> 1.6)
9
+ sinatra (~> 1.4)
10
+ slim (~> 3.0.1)
11
+ thin (~> 1.6)
12
+ thor (~> 0.19)
13
+ typhoeus (~> 0.6.9)
14
+ url_encryptor (~> 0.0.1)
15
+
16
+ GEM
17
+ remote: https://rubygems.org/
18
+ specs:
19
+ amq-protocol (1.9.2)
20
+ bunny (1.7.1)
21
+ amq-protocol (~> 1.9.2)
22
+ coderay (1.1.0)
23
+ daemons (1.2.3)
24
+ diff-lcs (1.2.5)
25
+ ethon (0.7.4)
26
+ ffi (>= 1.3.0)
27
+ eventmachine (1.0.8)
28
+ ffi (1.9.10)
29
+ method_source (0.8.2)
30
+ multi_json (1.11.2)
31
+ oj (2.12.12)
32
+ pry (0.10.1)
33
+ coderay (~> 1.1.0)
34
+ method_source (~> 0.8.1)
35
+ slop (~> 3.4)
36
+ rack (1.6.0)
37
+ rack-protection (1.5.3)
38
+ rack
39
+ rack-test (0.6.2)
40
+ rack (>= 1.0)
41
+ rake (10.4.2)
42
+ rr (1.1.2)
43
+ rspec (3.1.0)
44
+ rspec-core (~> 3.1.0)
45
+ rspec-expectations (~> 3.1.0)
46
+ rspec-mocks (~> 3.1.0)
47
+ rspec-core (3.1.7)
48
+ rspec-support (~> 3.1.0)
49
+ rspec-expectations (3.1.2)
50
+ diff-lcs (>= 1.2.0, < 2.0)
51
+ rspec-support (~> 3.1.0)
52
+ rspec-mocks (3.1.3)
53
+ rspec-support (~> 3.1.0)
54
+ rspec-support (3.1.2)
55
+ sinatra (1.4.6)
56
+ rack (~> 1.4)
57
+ rack-protection (~> 1.4)
58
+ tilt (>= 1.3, < 3)
59
+ slim (3.0.6)
60
+ temple (~> 0.7.3)
61
+ tilt (>= 1.3.3, < 2.1)
62
+ slop (3.6.0)
63
+ temple (0.7.6)
64
+ thin (1.6.3)
65
+ daemons (~> 1.0, >= 1.0.9)
66
+ eventmachine (~> 1.0)
67
+ rack (~> 1.0)
68
+ thor (0.19.1)
69
+ tilt (2.0.1)
70
+ typhoeus (0.6.9)
71
+ ethon (>= 0.7.1)
72
+ url_encryptor (0.0.1)
73
+ rack
74
+
75
+ PLATFORMS
76
+ ruby
77
+
78
+ DEPENDENCIES
79
+ action-server!
80
+ bundler (~> 1.7)
81
+ pry (~> 0.10)
82
+ rack-test (~> 0.6)
83
+ rake (~> 10.0)
84
+ rr (~> 1.1)
85
+ rspec (~> 3.1)
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "action-server"
7
+ spec.version = '0.0.1'
8
+ spec.authors = ["Alexander Vasin"]
9
+ spec.email = ["vad4msiu@gmail.com"]
10
+ spec.summary = %q{Action server}
11
+ spec.description = %q{Action server}
12
+ spec.homepage = "https://bitbucket.org/vad4msiu/action_server"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "multi_json", "~> 1.10"
21
+ spec.add_dependency "thor", "~> 0.19"
22
+ spec.add_dependency "thin", "~> 1.6"
23
+ spec.add_dependency "oj", "~> 2.10"
24
+ spec.add_dependency "bunny", "~> 1.6"
25
+ spec.add_dependency "sinatra", "~> 1.4"
26
+ spec.add_dependency 'slim', '~> 3.0.1'
27
+ spec.add_dependency 'typhoeus', '~> 0.6.9'
28
+ spec.add_dependency 'url_encryptor', '~> 0.0.1'
29
+ spec.add_dependency "rack", "~> 1.6"
30
+ spec.add_development_dependency "bundler", "~> 1.7"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rack-test", "~> 0.6"
33
+ spec.add_development_dependency "rspec", "~> 3.1"
34
+ spec.add_development_dependency "rr", "~> 1.1"
35
+ spec.add_development_dependency 'pry', '~> 0.10'
36
+ end
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'thor'
7
+ require 'action_server'
8
+
9
+ ENV['APP_ENV'] ||= ENV['RACK_ENV'] || 'development'
10
+
11
+ class ActionServerCLI < Thor
12
+ desc "start ...ARGS", "Run action server"
13
+
14
+ option 'queue_address', aliases: "-q", desc: "Queue address", default: 'localhost'
15
+ option 'queue_user', aliases: "-u", desc: "Queue user", default: 'enode'
16
+ option 'queue_password', aliases: "-p", desc: "Queue password", required: true
17
+ option 'host', aliases: "-h", desc: "Host address", required: true
18
+ option 'port', aliases: "-r", desc: "Port address", required: true
19
+ option 'cache_dir', aliases: "-c", desc: "Dir for cache", required: true
20
+
21
+ def start
22
+ ActionServer.rabbitmq_config = {
23
+ host: options['queue_address'],
24
+ user: options['queue_user'],
25
+ password: options['queue_password'],
26
+ vhost: ENV['APP_ENV']
27
+ }
28
+ ActionServer.cache_dir = options['cache_dir']
29
+
30
+ run ActionServer.run!(port: options['port'], bind: options['host'])
31
+ end
32
+ end
33
+
34
+ ActionServerCLI.start
@@ -0,0 +1,6 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'action_server'
5
+
6
+ run ActionServer
@@ -0,0 +1,148 @@
1
+ require 'sinatra/base'
2
+ require 'slim'
3
+ require 'bunny'
4
+ require 'multi_json'
5
+ require 'oj'
6
+ require 'url_encryptor'
7
+ require 'typhoeus'
8
+ require 'digest'
9
+
10
+ class ActionServer < Sinatra::Base
11
+ QUEUE_NAME = 'action'
12
+
13
+ class << self
14
+ attr_reader :rabbitmq_config, :queue, :cache_dir
15
+
16
+ def rabbitmq_config=(config)
17
+ @rabbitmq_config = config
18
+ end
19
+
20
+ def cache_dir=(path)
21
+ @cache_dir = path
22
+ end
23
+
24
+ def channel
25
+ @channel ||= begin
26
+ connection = Bunny.new(
27
+ host: rabbitmq_config[:host],
28
+ user: rabbitmq_config[:user],
29
+ password: rabbitmq_config[:password],
30
+ vhost: rabbitmq_config[:vhost]
31
+ )
32
+ connection.start
33
+ connection.create_channel
34
+ end
35
+ end
36
+
37
+ def exchange
38
+ @exchange ||= channel.default_exchange
39
+ end
40
+ end
41
+
42
+ def cache_dir
43
+ self.class.cache_dir
44
+ end
45
+
46
+
47
+ def publish(message)
48
+ self.class.exchange.publish(message, routing_key: QUEUE_NAME)
49
+ end
50
+
51
+ def extract_ip(request)
52
+ ip = request['HTTP_X_FORWARDED_FOR'] || request.ip
53
+ ip.to_s
54
+ end
55
+
56
+ def extract_headers(request)
57
+ headers = {}
58
+
59
+ request.env.each do |name, val|
60
+ header = name.match(/^HTTP_(.*)$/)
61
+ if header && header[1]
62
+ headers[header[1]] = val
63
+ end
64
+ end
65
+
66
+ headers
67
+ end
68
+
69
+ def md5(string)
70
+ md5 = Digest::MD5.new
71
+ md5.update(string)
72
+ md5.hexdigest
73
+ end
74
+
75
+ def downloaded_file(src, dest)
76
+ downloaded_file = nil
77
+ request = Typhoeus::Request.new(src, followlocation: true)
78
+
79
+ request.on_headers do |response|
80
+ if response.code == 200
81
+ downloaded_file = File.open(dest, 'wb')
82
+ else
83
+ error response.code
84
+ end
85
+ end
86
+
87
+ request.on_body do |chunk|
88
+ downloaded_file.write(chunk) if downloaded_file
89
+ end
90
+
91
+ request.on_complete do |response|
92
+ downloaded_file.close if downloaded_file
93
+ end
94
+
95
+ request.run
96
+ end
97
+
98
+ set :root, File.expand_path(File.join(File.dirname(__FILE__), '../'))
99
+ set :views, File.join(settings.root, 'views')
100
+ set :public_folder, File.join(settings.root, 'static')
101
+
102
+ not_found do
103
+ status 404
104
+ end
105
+
106
+ error OpenSSL::Cipher::CipherError do
107
+ status 404
108
+ end
109
+
110
+ get '/click/:data' do
111
+ query = UrlEncryptor.decrypt_query_string(params[:data])
112
+
113
+ message = MultiJson.dump(
114
+ action: 'click',
115
+ query: query,
116
+ headers: extract_headers(request)
117
+ )
118
+ publish(message)
119
+
120
+ redirect query["url"]
121
+ end
122
+
123
+ get '/open/:data' do
124
+ query = UrlEncryptor.decrypt_query_string(params[:data])
125
+
126
+ message = MultiJson.dump(
127
+ action: 'open',
128
+ query: query,
129
+ headers: extract_headers(request)
130
+ )
131
+ publish(message)
132
+
133
+ file_path = File.join(settings.public_folder, 'pixel.png')
134
+ send_file file_path, type: 'image/png', disposition: 'inline', filename: 'pixel.png'
135
+ end
136
+
137
+ get '/proxy/:data' do
138
+ query = UrlEncryptor.decrypt_query_string(params[:data])
139
+
140
+ file_name = "#{ md5(query["url"]) }.cache"
141
+ file = File.join(cache_dir, file_name)
142
+ unless File.exists?(file)
143
+ downloaded_file(query["url"], file)
144
+ end
145
+
146
+ send_file file
147
+ end
148
+ end
@@ -0,0 +1,84 @@
1
+ require "spec_helper"
2
+
3
+ describe ActionServer do
4
+ def app
5
+ ActionServer
6
+ end
7
+
8
+ let(:user_id) { '54aa4fd5e7998536b8fa78e1' }
9
+ let(:email_campaign_id) { '54a680d56d616927d3020000' }
10
+ let(:ip) { '127.0.0.1' }
11
+ let(:additional_params) { nil }
12
+ let(:message) {
13
+ MultiJson.dump(
14
+ ip: ip,
15
+ url: url,
16
+ user_id: user_id,
17
+ email_campaign_id: email_campaign_id
18
+ )
19
+ }
20
+
21
+ describe "get /click/:data" do
22
+ let(:query_string) { 'url=http://example.com&user_id=123' }
23
+ let(:encrypted_query_string) { UrlEncryptor.encrypt_query(query_string) }
24
+
25
+ before do
26
+ any_instance_of(ActionServer) do |klass|
27
+ stub(klass).publish
28
+ end
29
+ end
30
+
31
+ it "return successful response" do
32
+ get "/click/#{ encrypted_query_string }"
33
+
34
+ expect(last_response).to be_redirect
35
+ end
36
+ end
37
+
38
+ describe "get /open/:data" do
39
+ let(:query_string) { 'email=qwe@qwe.com&user_id=123' }
40
+ let(:encrypted_query_string) { UrlEncryptor.encrypt_query(query_string) }
41
+
42
+ before do
43
+ any_instance_of(ActionServer) do |klass|
44
+ stub(klass).publish
45
+ end
46
+ end
47
+
48
+ it "return successful response" do
49
+ get "/open/#{ encrypted_query_string }"
50
+
51
+ expect(last_response).to be_successful
52
+ end
53
+ end
54
+
55
+ describe "get /proxy/:data" do
56
+ before { ActionServer.cache_dir = '/tmp/' }
57
+
58
+ context 'with exists img' do
59
+ let(:url) { 'http://image.lascana.ru/pool/formatz/11570525.jpg' }
60
+ let(:cache_file_path) { '/tmp/e4d421d6763ffc0df34706c403440a2b.cache' }
61
+ let(:query_string) { "url=#{ url }&user_id=123" }
62
+ let(:encrypted_query_string) { UrlEncryptor.encrypt_query(query_string) }
63
+
64
+ it "return successful response" do
65
+ get "/proxy/#{ encrypted_query_string }"
66
+
67
+ expect(last_response).to be_successful
68
+ expect(File.exists?(cache_file_path)).to eq(true)
69
+ end
70
+ end
71
+
72
+ context 'without exists img' do
73
+ let(:url) { 'http://image.lascana.ru/qweqwe.jpg' }
74
+ let(:query_string) { "url=#{ url }&user_id=123" }
75
+ let(:encrypted_query_string) { UrlEncryptor.encrypt_query(query_string) }
76
+
77
+ it "return failure response" do
78
+ get "/proxy/#{ encrypted_query_string }"
79
+
80
+ expect(last_response.status).to eq(404)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,96 @@
1
+ require 'rr'
2
+ require 'rack/test'
3
+ require_relative '../lib/action_server'
4
+
5
+ # This file was generated by the `rspec --init` command. Conventionally, all
6
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
8
+ # file to always be loaded, without a need to explicitly require it in any files.
9
+ #
10
+ # Given that it is always loaded, you are encouraged to keep this file as
11
+ # light-weight as possible. Requiring heavyweight dependencies from this file
12
+ # will add to the boot time of your test suite on EVERY test run, even for an
13
+ # individual file that may not need all of that loaded. Instead, consider making
14
+ # a separate helper file that requires the additional dependencies and performs
15
+ # the additional setup, and require it from the spec files that actually need it.
16
+ #
17
+ # The `.rspec` file also contains a few flags that are not defaults but that
18
+ # users commonly want.
19
+ #
20
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
+ RSpec.configure do |config|
22
+ config.include Rack::Test::Methods
23
+
24
+ # rspec-expectations config goes here. You can use an alternate
25
+ # assertion/expectation library such as wrong or the stdlib/minitest
26
+ # assertions if you prefer.
27
+ config.expect_with :rspec do |expectations|
28
+ # This option will default to `true` in RSpec 4. It makes the `description`
29
+ # and `failure_message` of custom matchers include text for helper methods
30
+ # defined using `chain`, e.g.:
31
+ # be_bigger_than(2).and_smaller_than(4).description
32
+ # # => "be bigger than 2 and smaller than 4"
33
+ # ...rather than:
34
+ # # => "be bigger than 2"
35
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
36
+ end
37
+
38
+ # rspec-mocks config goes here. You can use an alternate test double
39
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
40
+ # config.mock_with :rspec do |mocks|
41
+ # # Prevents you from mocking or stubbing a method that does not exist on
42
+ # # a real object. This is generally recommended, and will default to
43
+ # # `true` in RSpec 4.
44
+ # mocks.verify_partial_doubles = true
45
+ # end
46
+ config.mock_with :rr
47
+
48
+ # The settings below are suggested to provide a good initial experience
49
+ # with RSpec, but feel free to customize to your heart's content.
50
+ =begin
51
+ # These two settings work together to allow you to limit a spec run
52
+ # to individual examples or groups you care about by tagging them with
53
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
54
+ # get run.
55
+ config.filter_run :focus
56
+ config.run_all_when_everything_filtered = true
57
+
58
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
59
+ # For more details, see:
60
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
61
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
62
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
63
+ config.disable_monkey_patching!
64
+
65
+ # This setting enables warnings. It's recommended, but in some cases may
66
+ # be too noisy due to issues in dependencies.
67
+ config.warnings = true
68
+
69
+ # Many RSpec users commonly either run the entire suite or an individual
70
+ # file, and it's useful to allow more verbose output when running an
71
+ # individual spec file.
72
+ if config.files_to_run.one?
73
+ # Use the documentation formatter for detailed output,
74
+ # unless a formatter has already been configured
75
+ # (e.g. via a command-line flag).
76
+ config.default_formatter = 'doc'
77
+ end
78
+
79
+ # Print the 10 slowest examples and example groups at the
80
+ # end of the spec run, to help surface which specs are running
81
+ # particularly slow.
82
+ config.profile_examples = 10
83
+
84
+ # Run specs in random order to surface order dependencies. If you find an
85
+ # order dependency and want to debug it, you can fix the order by providing
86
+ # the seed, which is printed after each run.
87
+ # --seed 1234
88
+ config.order = :random
89
+
90
+ # Seed global randomization in this process using the `--seed` CLI option.
91
+ # Setting this allows you to use `--seed` to deterministically reproduce
92
+ # test failures related to randomization by passing the same `--seed` value
93
+ # as the one that triggered the failure.
94
+ Kernel.srand config.seed
95
+ =end
96
+ end
Binary file
@@ -0,0 +1,5 @@
1
+ doctype html
2
+ html
3
+ head
4
+ javascript:
5
+ window.location = "#{{ url }}";
metadata ADDED
@@ -0,0 +1,284 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: action-server
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Vasin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.19'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.19'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thin
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: oj
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.10'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bunny
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.6'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sinatra
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.4'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: slim
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.0.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.0.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: typhoeus
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.6.9
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.6.9
125
+ - !ruby/object:Gem::Dependency
126
+ name: url_encryptor
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.0.1
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.0.1
139
+ - !ruby/object:Gem::Dependency
140
+ name: rack
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.6'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.6'
153
+ - !ruby/object:Gem::Dependency
154
+ name: bundler
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.7'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.7'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rake
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '10.0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '10.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rack-test
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '0.6'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '0.6'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rspec
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '3.1'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '3.1'
209
+ - !ruby/object:Gem::Dependency
210
+ name: rr
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '1.1'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '1.1'
223
+ - !ruby/object:Gem::Dependency
224
+ name: pry
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '0.10'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '0.10'
237
+ description: Action server
238
+ email:
239
+ - vad4msiu@gmail.com
240
+ executables:
241
+ - action-server
242
+ extensions: []
243
+ extra_rdoc_files: []
244
+ files:
245
+ - ".gitignore"
246
+ - ".rspec"
247
+ - Gemfile
248
+ - Gemfile.lock
249
+ - Rakefile
250
+ - action_server.gemspec
251
+ - bin/action-server
252
+ - config.ru
253
+ - lib/action_server.rb
254
+ - spec/lib/action_server_spec.rb
255
+ - spec/spec_helper.rb
256
+ - static/pixel.png
257
+ - views/click.slim
258
+ homepage: https://bitbucket.org/vad4msiu/action_server
259
+ licenses:
260
+ - MIT
261
+ metadata: {}
262
+ post_install_message:
263
+ rdoc_options: []
264
+ require_paths:
265
+ - lib
266
+ required_ruby_version: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - ">="
269
+ - !ruby/object:Gem::Version
270
+ version: '0'
271
+ required_rubygems_version: !ruby/object:Gem::Requirement
272
+ requirements:
273
+ - - ">="
274
+ - !ruby/object:Gem::Version
275
+ version: '0'
276
+ requirements: []
277
+ rubyforge_project:
278
+ rubygems_version: 2.4.5
279
+ signing_key:
280
+ specification_version: 4
281
+ summary: Action server
282
+ test_files:
283
+ - spec/lib/action_server_spec.rb
284
+ - spec/spec_helper.rb