redsquare 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e01942bde738c4203eeae03cc1e61c3a8a423c4
4
- data.tar.gz: 655f6d5f299cf87753e7045d061a820c93474c9d
3
+ metadata.gz: dbc88f827c0b6a085537558c2a5ad96084fe1999
4
+ data.tar.gz: 92409c95a47bd14731bbf08aaaf5f7de4c70289c
5
5
  SHA512:
6
- metadata.gz: 0bdea34c85ecf6be10c97fee60fb659ff8dba8ec2b6f3734a3ca16e3be30c2d2b674a765b6b03b125ce25a08fc7540df21e5a6c21ed9c2e9602ace0427ccd342
7
- data.tar.gz: e166d7f76a00d41c721b15dcb7426daffc364dd5016bf404014fc33e4cab7097ea3f27c0899108b83d15b177b9fe1110592f50c73e3e816523e71fcace252a59
6
+ metadata.gz: 03465cef0c7afead904f05e843824e1f412905ef3e3f8667a3743506e86b3b041c01b8eed37232833929f7b0182f5687df035c85e81661dcb8f7b832ea8bf870
7
+ data.tar.gz: 792e2aca3fcb850ddb611dab6eca700a07eb9077c4189d6d19b09a23bb4cde4ce7c1f55868c402e9ba3a2253b7747e6b95731754df67810678038025be161d79
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Redsquare
2
2
 
3
- TODO: Write a gem description
3
+ Redsquare provides an HTTP interface for Redis that can be launched as a
4
+ standalone Sinatra app or mounted within a Rails application.
4
5
 
5
6
  ## Installation
6
7
 
@@ -16,9 +17,195 @@ Or install it yourself as:
16
17
 
17
18
  $ gem install redsquare
18
19
 
20
+ ## Setup
21
+
22
+ ### Configuration
23
+
24
+ Redsquare config begins and ends with setting a connection to the Redis
25
+ instance you want to use. If you specify none, then you'll get a
26
+ connection to localhost on the default Redis port. If you want to
27
+ specify a connection, use the following:
28
+
29
+ ```ruby
30
+ Redsquare.configure do |config|
31
+
32
+ # set it to an existing connection
33
+ config.redis = Redis.current
34
+
35
+ # pass a config hash that will be passed to Redis.new
36
+ config.redis = { :host => 'localhost', :port => 6379 }
37
+
38
+ end
39
+ ```
40
+
41
+ ### Standalone Server
42
+
43
+ Simply run Redsquare from the command line.
44
+
45
+ ```
46
+ redsquare
47
+
48
+ redsquare ~/some/path/to/redsquare_config.rb
49
+ ```
50
+
51
+ ### Mounting Within a Rails App
52
+
53
+ In your `routes.rb` file simplye mount the `Redsquare::App` module.
54
+
55
+ ```ruby
56
+ YourApp::Application.routes.draw do
57
+ mount Redsquare::App => "/redis"
58
+ end
59
+ ```
60
+
19
61
  ## Usage
20
62
 
21
- TODO: Write usage instructions here
63
+ Using Redsquare is very simple. Commands are divided into two
64
+ categories, those you issue with an HTTP POST call and those you issue
65
+ with an HTTP GET call. The examples below will be in JavaScript but you
66
+ can easily call Redsquare endpoints form anywhere.
67
+
68
+ ### GET Commands
69
+
70
+ The following are the Redis commands which Redsquare knows about that
71
+ can be called with a GET request:
72
+
73
+ ```
74
+ dbsize
75
+ exists
76
+ get
77
+ getbit
78
+ getrange
79
+ hexists
80
+ hget
81
+ hgetall
82
+ hkeys
83
+ hlen
84
+ hmget
85
+ hvals
86
+ keys
87
+ lindex
88
+ llen
89
+ lrange
90
+ mget
91
+ pttl
92
+ randomkey
93
+ scard
94
+ sdiff
95
+ sinter
96
+ sismember
97
+ smembers
98
+ srandmember
99
+ sunion
100
+ ```
101
+
102
+ The URL format for GET commands is straightforward:
103
+
104
+ ```
105
+ GET /<command>/<arg1>/<arg2>/<arg...>
106
+ ```
107
+
108
+ Some examples:
109
+
110
+ ```
111
+ GET /get/somekey
112
+ GET /keys
113
+ GET /hget/somekey/somefield
114
+ ```
115
+
116
+ The return value is a simple JSON object:
117
+
118
+ ```javascript
119
+ // GET /get/somekey
120
+ { result: "foo" }
121
+
122
+ // GET /keys
123
+ { result: ["somekey", "someotherkey"]
124
+
125
+ // GET /hget/somekey/somefield
126
+ { result: "baz" }
127
+ ```
128
+
129
+ ### POST Commands
130
+
131
+ The following are the Redis commands which Redsquare knows about that
132
+ can be called with a POST request:
133
+
134
+ ```
135
+ sunionstore
136
+ srem
137
+ spop
138
+ smove
139
+ setrange
140
+ setnx
141
+ setbit
142
+ set
143
+ sdiffstore
144
+ sadd
145
+ rpush
146
+ rpoplpush
147
+ rpop
148
+ renamex
149
+ rename
150
+ psetex
151
+ pexpireat
152
+ pexpire
153
+ persist
154
+ msetnx
155
+ mset
156
+ ltrim
157
+ lset
158
+ lrem
159
+ lpushx
160
+ lpush
161
+ lpop
162
+ linsert
163
+ incrbyfloat
164
+ incrby
165
+ incr
166
+ hsetnx
167
+ hset
168
+ hmset
169
+ hincrbyfloat
170
+ hincrby
171
+ hdel
172
+ getset
173
+ expireat
174
+ expire
175
+ del
176
+ decrby
177
+ decr
178
+ append
179
+ ```
180
+
181
+ Because these are POST commands and the arguments may be more complex
182
+ types than simple strings the semantics of the request are slightly
183
+ different. Each URL follows the same format:
184
+
185
+ ```
186
+ POST /<command>
187
+ ```
188
+
189
+ Arguments are supplied via the POST parameter `args` which is an array
190
+ of arguments in the order that they would be passed to the underlying
191
+ Redis method. For example:
192
+
193
+ ```javascript
194
+ // Sets the 'somefield' field of the hash at key 'somekey' to 42
195
+ $.post("/hset", { args: ["somekey", "somefield", 42] });
196
+
197
+ // Increments the key at 'somekey' by 12
198
+ $.post("/incrby", { args: ["somekey", 12] });
199
+ ```
200
+
201
+ The return value for POST commands is the same for GET commands, a
202
+ simple JSON hash with a `results` key containing the serialized return
203
+ value of the Redis call.
204
+
205
+ ## TODO:
206
+
207
+ * Not all of the Redis commands are currently supported.
208
+ * Add support for Redis pub/sub.
22
209
 
23
210
  ## Contributing
24
211
 
data/bin/redsquare CHANGED
@@ -1,12 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- begin
3
+ def run
4
4
  require "redsquare"
5
+ require File.expand_path(ARGV[0]) if ARGV[0]
5
6
  Redsquare::App.run!
7
+ end
8
+
9
+ begin
10
+ run
6
11
  rescue LoadError => e
7
12
  require "rubygems"
8
13
  path = File.expand_path "../../lib", __FILE__
9
14
  $:.unshift(path) if File.directory?(path) && !$:.include?(path)
10
- require "redsquare"
11
- Redsquare::App.run!
15
+ run
12
16
  end
@@ -2,6 +2,10 @@ module Redsquare
2
2
  class App < Sinatra::Base
3
3
 
4
4
  POST_COMMANDS = [
5
+ :sunionstore,
6
+ :srem,
7
+ :spop,
8
+ :smove,
5
9
  :setrange,
6
10
  :setnx,
7
11
  :setbit,
@@ -45,6 +49,10 @@ module Redsquare
45
49
  ]
46
50
 
47
51
  GET_COMMANDS = [
52
+ :sunion,
53
+ :srandmember,
54
+ :smembers,
55
+ :sismember,
48
56
  :sinter,
49
57
  :sdiff,
50
58
  :scard,
@@ -66,15 +74,14 @@ module Redsquare
66
74
  :getbit,
67
75
  :get,
68
76
  :exists,
69
- :dump,
70
77
  :dbsize
71
78
  ]
72
79
 
73
80
  POST_COMMANDS.each do |command|
74
- post "/#{command}/?*" do
81
+ post "/#{command}" do
75
82
  content_type :json
76
- args = params[:splat].select { |a| a.present? }.compact
77
- val = Redis.current.send command, *args
83
+ args = params[:args].map { |a| try_to_i a }
84
+ val = Config.redis.send command, *args
78
85
  { result: val }.to_json
79
86
  end
80
87
  end
@@ -82,11 +89,16 @@ module Redsquare
82
89
  GET_COMMANDS.each do |command|
83
90
  get "/#{command}/?*" do
84
91
  content_type :json
85
- args = params[:splat][0].split("/")
86
- val = Redis.current.send command, *args
92
+ args = params[:splat][0].split("/").map { |a| try_to_i a }
93
+ val = Config.redis.send command, *args
87
94
  { result: val }.to_json
88
95
  end
89
96
  end
90
97
 
98
+ def try_to_i(str)
99
+ is_int = str.to_i.to_s == str
100
+ is_int ? str.to_i : str
101
+ end
102
+
91
103
  end
92
104
  end
@@ -0,0 +1,18 @@
1
+ module Redsquare
2
+ module Config
3
+ extend self
4
+
5
+ def redis=(arg)
6
+ if arg.is_a?(Redis)
7
+ @redis = arg
8
+ else
9
+ @redis = Redis.new(arg)
10
+ end
11
+ end
12
+
13
+ def redis
14
+ @redis ||= Redis.current
15
+ end
16
+
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module Redsquare
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/redsquare.rb CHANGED
@@ -3,4 +3,13 @@ require "active_support/all"
3
3
  require "sinatra"
4
4
  require "redis"
5
5
  require "json"
6
- require "redsquare/application/app"
6
+ require "redsquare/config"
7
+ require "redsquare/app"
8
+
9
+ module Redsquare
10
+
11
+ def config
12
+ Config
13
+ end
14
+
15
+ end
data/redsquare.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.name = "redsquare"
9
9
  spec.version = Redsquare::VERSION
10
10
  spec.authors = ["JC Grubbs"]
11
- spec.email = ["jc.grubbs@devmynd.com"]
12
- spec.description = %q{Redsquare is a server that supplies a restful interface to Redis.}
13
- spec.summary = %q{Redsquare is a server that supplies a restful interface to Redis.}
11
+ spec.email = ["jc@devmynd.com"]
12
+ spec.description = %q{A mountable/standalone JSON interface to Redis.}
13
+ spec.summary = %q{A mountable/standalone JSON interface to Redis.}
14
14
  spec.homepage = "http://github.com/thegrubbsian/redsquare"
15
15
  spec.license = "MIT"
16
16
 
@@ -27,4 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rake"
28
28
  spec.add_development_dependency "rspec"
29
29
  spec.add_development_dependency "pry"
30
+ spec.add_development_dependency "rack-test"
31
+ spec.add_development_dependency "fakeredis"
32
+
30
33
  end
data/spec/app_spec.rb ADDED
@@ -0,0 +1,197 @@
1
+ require "spec_helper"
2
+
3
+ describe Redsquare::App do
4
+ include Rack::Test::Methods
5
+
6
+ def app
7
+ Redsquare::App
8
+ end
9
+
10
+ def result
11
+ JSON.parse(last_response.body)["result"]
12
+ end
13
+
14
+ def redis
15
+ Redis.current
16
+ end
17
+
18
+ describe "GET commands" do
19
+
20
+ before do
21
+
22
+ # String
23
+ redis.set "string_a", "bar"
24
+ redis.set "string_b", "baz"
25
+
26
+ # Sets
27
+ redis.sadd "set_a", "a"
28
+ redis.sadd "set_a", "b"
29
+ redis.sadd "set_a", "c"
30
+
31
+ redis.sadd "set_b", "b"
32
+ redis.sadd "set_b", "c"
33
+ redis.sadd "set_b", "d"
34
+
35
+ # Lists
36
+ redis.rpush "list_a", "a"
37
+ redis.rpush "list_a", "b"
38
+ redis.rpush "list_a", "c"
39
+
40
+ redis.rpush "list_b", "b"
41
+ redis.rpush "list_b", "c"
42
+ redis.rpush "list_b", "d"
43
+
44
+ # Expiring key
45
+ redis.set "expire", "foo"
46
+ redis.expireat "expireat", 1555555555005
47
+
48
+ # Hashes
49
+ redis.hset "hash_a", "a", 1
50
+ redis.hset "hash_a", "b", 2.00
51
+ redis.hset "hash_a", "c", "foobar"
52
+ end
53
+
54
+ describe "returns the correct response for" do
55
+
56
+ it "sinter" do
57
+ get "/sinter/set_a/set_b"
58
+ expect(result).to eq ["b", "c"]
59
+ end
60
+
61
+ it "sdiff" do
62
+ get "/sdiff/set_a/set_b"
63
+ expect(result).to eq ["a"]
64
+ get "/sdiff/set_b/set_a"
65
+ expect(result).to eq ["d"]
66
+ end
67
+
68
+ it "scard" do
69
+ get "/scard/set_a"
70
+ expect(result).to eq 3
71
+ end
72
+
73
+ it "randomkey" do
74
+ get "/randomkey"
75
+ expect(result).to_not be_nil
76
+ end
77
+
78
+ it "mget" do
79
+ get "/mget/string_a/string_b"
80
+ expect(result).to eq ["bar", "baz"]
81
+ end
82
+
83
+ it "lrange" do
84
+ get "/lrange/list_a/0/1"
85
+ expect(result).to eq ["a", "b"]
86
+ end
87
+
88
+ it "llen" do
89
+ get "/llen/list_a"
90
+ expect(result).to eq 3
91
+ end
92
+
93
+ it "lindex" do
94
+ get "/lindex/list_a/1"
95
+ expect(result).to eq "b"
96
+ end
97
+
98
+ it "keys" do
99
+ get "/keys"
100
+ expect(result).to eq Redis.current.keys
101
+ end
102
+
103
+ it "hvals" do
104
+ get "/hvals/hash_a"
105
+ expect(result).to eq ["1", "2.0", "foobar"]
106
+ end
107
+
108
+ it "hmget" do
109
+ get "/hmget/hash_a/a/c"
110
+ expect(result).to eq ["1", "foobar"]
111
+ end
112
+
113
+ it "hlen" do
114
+ get "/hlen/hash_a"
115
+ expect(result).to eq 3
116
+ end
117
+
118
+ it "hkeys" do
119
+ get "/hkeys/hash_a"
120
+ expect(result).to eq ["a", "b", "c"]
121
+ end
122
+
123
+ it "hgetall" do
124
+ get "/hgetall/hash_a"
125
+ expect(result).to eq({ "a" => "1", "b" => "2.0", "c" => "foobar" })
126
+ end
127
+
128
+ it "hget" do
129
+ get "/hget/hash_a/a"
130
+ expect(result).to eq "1"
131
+ end
132
+
133
+ it "hexists" do
134
+ get "/hexists/hash_a/c"
135
+ expect(result).to be_true
136
+ end
137
+
138
+ it "getrange" do
139
+ get "/getrange/string_a/0/1"
140
+ expect(result).to eq "ba"
141
+ end
142
+
143
+ it "get" do
144
+ get "/get/string_a"
145
+ expect(result).to eq "bar"
146
+ end
147
+
148
+ it "exists" do
149
+ get "/get/string_a"
150
+ expect(result).to be_true
151
+ end
152
+
153
+ it "dbsize" do
154
+ get "/dbsize"
155
+ expect(result).to eq 8
156
+ end
157
+
158
+ end
159
+
160
+ end
161
+
162
+ describe "POST commands" do
163
+
164
+ describe "returns the correct response for" do
165
+
166
+ it "setrange" do
167
+ redis.set "string_a", "Hello World"
168
+ post "/setrange", args: ["string_a", 6, "Redis"]
169
+ expect(redis.get "string_a").to eq "Hello Redis"
170
+ end
171
+
172
+ it "setnx" do
173
+ post "/setnx", args: ["bar", "baz"]
174
+ expect(redis.get "bar").to eq "baz"
175
+ end
176
+
177
+ it "set" do
178
+ post "/set", args: ["string_a", "foo"]
179
+ expect(redis.get "string_a").to eq "foo"
180
+ end
181
+
182
+ it "sdiffstore" do
183
+ redis.sadd "list_a", "a"
184
+ redis.sadd "list_a", "b"
185
+ redis.sadd "list_a", "c"
186
+ redis.sadd "list_b", "b"
187
+ redis.sadd "list_b", "c"
188
+ redis.sadd "list_b", "d"
189
+ post "/sdiffstore", args: ["list_c", "list_a", "list_b"]
190
+ expect(redis.smembers "list_c").to eq ["a"]
191
+ end
192
+
193
+ end
194
+
195
+ end
196
+
197
+ end
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+ require "redsquare"
3
+ require "rack/test"
4
+ require "fakeredis/rspec"
5
+ require "pry"
6
+
7
+ set :environment, :test
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec
11
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redsquare
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JC Grubbs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-29 00:00:00.000000000 Z
11
+ date: 2013-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -108,9 +108,37 @@ dependencies:
108
108
  - - '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- description: Redsquare is a server that supplies a restful interface to Redis.
111
+ - !ruby/object:Gem::Dependency
112
+ name: rack-test
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: fakeredis
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: A mountable/standalone JSON interface to Redis.
112
140
  email:
113
- - jc.grubbs@devmynd.com
141
+ - jc@devmynd.com
114
142
  executables:
115
143
  - redsquare
116
144
  extensions: []
@@ -123,10 +151,12 @@ files:
123
151
  - Rakefile
124
152
  - bin/redsquare
125
153
  - lib/redsquare.rb
126
- - lib/redsquare/application/app.rb
127
- - lib/redsquare/application/commands/keys.rb
154
+ - lib/redsquare/app.rb
155
+ - lib/redsquare/config.rb
128
156
  - lib/redsquare/version.rb
129
157
  - redsquare.gemspec
158
+ - spec/app_spec.rb
159
+ - spec/spec_helper.rb
130
160
  homepage: http://github.com/thegrubbsian/redsquare
131
161
  licenses:
132
162
  - MIT
@@ -150,5 +180,7 @@ rubyforge_project:
150
180
  rubygems_version: 2.0.2
151
181
  signing_key:
152
182
  specification_version: 4
153
- summary: Redsquare is a server that supplies a restful interface to Redis.
154
- test_files: []
183
+ summary: A mountable/standalone JSON interface to Redis.
184
+ test_files:
185
+ - spec/app_spec.rb
186
+ - spec/spec_helper.rb
@@ -1,17 +0,0 @@
1
- module Commands
2
- module Keys
3
-
4
- def self.included(klass)
5
- redis = Redis.current
6
-
7
- klass.class_eval do
8
-
9
- get "/keys/(:pattern)" do
10
- redis.keys
11
- end
12
-
13
- end
14
- end
15
-
16
- end
17
- end