udp_rest 0.9.0
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
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +24 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/demo/simple_server.rb +41 -0
- data/exe/udp-rest +3 -0
- data/lib/rest_client.rb +42 -0
- data/lib/udp_rest.rb +139 -0
- data/lib/udp_rest/udp.rb +71 -0
- data/lib/udp_rest/uhttp.rb +72 -0
- data/lib/udp_rest/version.rb +3 -0
- data/lib/worker_thread.rb +42 -0
- data/readme.md +35 -0
- data/udp_rest.gemspec +27 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5c547a1a4aeafe5240118f42f1d060b861bba377
|
4
|
+
data.tar.gz: 1f67cc942b89d5d8da7b12066d019b96eaa54cf1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 637dbc37f4e52a049b500f09aa60dcf167f27434fcfc9c2ea5c5fe8b442fc128e1d8cccf6b35c14ea42f3596c135cd1df3b03a1a5dea8f34f663dc8d56ebac33
|
7
|
+
data.tar.gz: e592fdfff3610df362d4a558d15bda20dde2b61302f4bafdb1ddbaebca62053291e71f101e349308ea8eb849725ae21e3cb6050ba5bcaaaa44fdb0b5d780ac0e
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
udp_rest (0.9.0)
|
5
|
+
colorize
|
6
|
+
trollop
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
colorize (0.8.1)
|
12
|
+
rake (10.5.0)
|
13
|
+
trollop (2.1.2)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
bundler (~> 1.12)
|
20
|
+
rake (~> 10.0)
|
21
|
+
udp_rest!
|
22
|
+
|
23
|
+
BUNDLED WITH
|
24
|
+
1.12.5
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Nathan Reed
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "udp_rest"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'time'
|
5
|
+
require 'udp_rest'
|
6
|
+
|
7
|
+
req_count = 0
|
8
|
+
port = (ARGV.last || 7890).to_i
|
9
|
+
puts "listening on 0.0.0.0:#{port}..."
|
10
|
+
|
11
|
+
UDPRest::Server.new(:port => port) do |s|
|
12
|
+
s.get '/' do
|
13
|
+
"Hello, World!\nVisit http://github.com/reednj/udp_rest for more info"
|
14
|
+
end
|
15
|
+
|
16
|
+
s.get '/hello' do
|
17
|
+
'hello'
|
18
|
+
end
|
19
|
+
|
20
|
+
s.post '/time' do
|
21
|
+
Time.now.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
s.get '/time/unix' do
|
25
|
+
Time.now.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
s.get '/time/iso' do
|
29
|
+
Time.now.iso8601
|
30
|
+
end
|
31
|
+
|
32
|
+
s.get '/count' do
|
33
|
+
req_count += 1
|
34
|
+
req_count.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
s.get '/too_long' do
|
38
|
+
'a' * 600
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/exe/udp-rest
ADDED
data/lib/rest_client.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'colorize'
|
5
|
+
require 'trollop'
|
6
|
+
require 'udp_rest'
|
7
|
+
|
8
|
+
class App
|
9
|
+
def main
|
10
|
+
valid_methods = ['GET', 'PUT', 'POST', 'DELETE']
|
11
|
+
@opts = Trollop::options do
|
12
|
+
version "UDP RestClient (c) 2016 @reednj"
|
13
|
+
banner "Usage: udp-rest [options] <url>"
|
14
|
+
opt :method, "HTTP Method (GET, POST etc)", :type => :string, :default => 'GET'
|
15
|
+
opt :headers, "Show the response headers", :default => false
|
16
|
+
end
|
17
|
+
|
18
|
+
Trollop::educate if ARGV.empty?
|
19
|
+
url = ARGV.last
|
20
|
+
url = "uhttp://" + url unless url.start_with? 'uhttp://'
|
21
|
+
|
22
|
+
begin
|
23
|
+
if !valid_methods.include? @opts[:method].upcase
|
24
|
+
raise "Invalid REST method '#{@opts[:method]}'"
|
25
|
+
end
|
26
|
+
|
27
|
+
r = UDPRest::Client.uhttp(@opts[:method], url)
|
28
|
+
print_response(r)
|
29
|
+
rescue => e
|
30
|
+
puts e
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def print_response(r)
|
35
|
+
if @opts[:headers]
|
36
|
+
puts r.ok? ? r.status_line.green : r.status_line.red
|
37
|
+
puts ''
|
38
|
+
end
|
39
|
+
|
40
|
+
puts r.text
|
41
|
+
end
|
42
|
+
end
|
data/lib/udp_rest.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
require 'worker_thread'
|
5
|
+
require "udp_rest/version"
|
6
|
+
require "udp_rest/udp"
|
7
|
+
require "udp_rest/uhttp"
|
8
|
+
|
9
|
+
module UDPRest
|
10
|
+
class Server
|
11
|
+
def initialize(options = {})
|
12
|
+
@udp = UDPServer.new
|
13
|
+
@routes = {}
|
14
|
+
|
15
|
+
if block_given?
|
16
|
+
yield(self)
|
17
|
+
port = options[:port] || 80
|
18
|
+
options[:host] = options[:host] || '0.0.0.0'
|
19
|
+
self.listen(port, options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def udp_server
|
24
|
+
@udp
|
25
|
+
end
|
26
|
+
|
27
|
+
def post(path, &block)
|
28
|
+
add_route('POST', path, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(path, &block)
|
32
|
+
add_route('GET', path, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_route(req_method, path, &block)
|
36
|
+
key = "#{req_method.upcase} #{path}"
|
37
|
+
@routes[key] = Proc.new &block
|
38
|
+
return key
|
39
|
+
end
|
40
|
+
|
41
|
+
def route_request(request)
|
42
|
+
key = "#{request.req_method.upcase} #{request.path}"
|
43
|
+
puts key
|
44
|
+
|
45
|
+
block = @routes[key]
|
46
|
+
return respond(404, 'Not Found') if block.nil?
|
47
|
+
|
48
|
+
# handle the response. No matter what gets returned
|
49
|
+
# we want to try and make it into something useful
|
50
|
+
result = block.call(request, self)
|
51
|
+
return result if result.is_a? UHTTPResponse
|
52
|
+
return respond(200, result.to_s) if result.respond_to? :to_s
|
53
|
+
return respond(200, 'ok')
|
54
|
+
end
|
55
|
+
|
56
|
+
def listen(port, options = {})
|
57
|
+
port = port || 80
|
58
|
+
|
59
|
+
@udp.listen(port, options) do |packet|
|
60
|
+
response = nil
|
61
|
+
|
62
|
+
if response.nil?
|
63
|
+
begin
|
64
|
+
request = UHTTPRequest.from_packet packet
|
65
|
+
rescue => e
|
66
|
+
puts "400 BAD REQUEST: #{e}"
|
67
|
+
response = respond(400, 'Bad Request')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if response.nil?
|
72
|
+
begin
|
73
|
+
response = route_request(request)
|
74
|
+
|
75
|
+
if response.to_s.bytesize > udp_server.max_packet_size
|
76
|
+
raise "response too long (#{response.to_s.bytesize} bytes)"
|
77
|
+
end
|
78
|
+
rescue => e
|
79
|
+
puts "500 APPLICATION ERROR: #{e}"
|
80
|
+
response = respond(500, 'Application Error')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
@udp.send(response.to_s, packet.src_addr, packet.src_port)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def respond(code, text)
|
89
|
+
UHTTPResponse.new(code, :text => text)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Client
|
94
|
+
attr_accessor :host
|
95
|
+
attr_accessor :port
|
96
|
+
attr_accessor :socket
|
97
|
+
attr_accessor :timeout
|
98
|
+
|
99
|
+
def initialize(host, port)
|
100
|
+
@max_packet_size = 512
|
101
|
+
|
102
|
+
self.host = host
|
103
|
+
self.port = port
|
104
|
+
self.socket = UDPSocket.new
|
105
|
+
self.timeout = 5.0
|
106
|
+
end
|
107
|
+
|
108
|
+
def send_text(text)
|
109
|
+
thread = WorkerThread.new.start :timeout => self.timeout do
|
110
|
+
self.socket.send(text, 0, self.host, self.port)
|
111
|
+
response_data = self.socket.recvfrom(@max_packet_size)
|
112
|
+
UDPPacket.new(response_data)
|
113
|
+
end
|
114
|
+
|
115
|
+
thread.join
|
116
|
+
packet = thread.value
|
117
|
+
raise "Request Timeout (#{host}:#{port})" if packet.nil?
|
118
|
+
return packet
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.uhttp(req_method, url)
|
122
|
+
uri = URI(url)
|
123
|
+
client = self.new(uri.host, uri.port || 80)
|
124
|
+
|
125
|
+
req = UHTTPRequest.new
|
126
|
+
req.req_method = req_method
|
127
|
+
req.path = uri.path
|
128
|
+
|
129
|
+
packet = client.send_text(req.to_s)
|
130
|
+
UHTTPResponse.parse(packet.text)
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.get(url)
|
134
|
+
self.uhttp('GET', url)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
data/lib/udp_rest/udp.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
module UDPRest
|
5
|
+
|
6
|
+
class UDPRest::UDPServer
|
7
|
+
attr_accessor :socket
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@max_packet_size = 512
|
11
|
+
self.socket = UDPSocket.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def max_packet_size
|
15
|
+
@max_packet_size
|
16
|
+
end
|
17
|
+
|
18
|
+
def listen(port, options = {})
|
19
|
+
@port = port.to_i
|
20
|
+
@host = options[:host] || '0.0.0.0'
|
21
|
+
self.socket.bind(@host, @port)
|
22
|
+
|
23
|
+
loop do
|
24
|
+
response = self.receive()
|
25
|
+
yield(response)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def receive
|
30
|
+
data = self.socket.recvfrom(@max_packet_size)
|
31
|
+
UDPPacket.new(data)
|
32
|
+
end
|
33
|
+
|
34
|
+
def send(text, host, port)
|
35
|
+
raise "message too long (max is #{@max_packet_size}b, was #{text.bytesize})" if text.bytesize > @max_packet_size
|
36
|
+
self.socket.send(text, 0, host, port)
|
37
|
+
end
|
38
|
+
|
39
|
+
def host
|
40
|
+
@host
|
41
|
+
end
|
42
|
+
|
43
|
+
def port
|
44
|
+
@port
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class UDPRest::UDPPacket
|
50
|
+
attr_accessor :text
|
51
|
+
attr_accessor :addr_family
|
52
|
+
attr_accessor :src_port
|
53
|
+
attr_accessor :src_addr
|
54
|
+
|
55
|
+
def initialize(data = nil)
|
56
|
+
# assume this was initialized with the standard data structure
|
57
|
+
# that is returned by UDPSocket
|
58
|
+
if !data.nil?
|
59
|
+
self.text = data[0]
|
60
|
+
self.addr_family = data[1][0]
|
61
|
+
self.src_port = data[1][1]
|
62
|
+
self.src_addr = data[1][2]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
self.text
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
module UDPRest
|
5
|
+
|
6
|
+
class UDPRest::UHTTPRequest
|
7
|
+
attr_accessor :req_method
|
8
|
+
attr_accessor :path
|
9
|
+
attr_accessor :protocol
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
self.req_method = 'GET'
|
13
|
+
self.protocol = 'UHTTP/1.0'
|
14
|
+
self.path ='/'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_packet(p)
|
18
|
+
text = p
|
19
|
+
text = p.text if text.is_a? UDPPacket
|
20
|
+
data = text.split(' ')
|
21
|
+
|
22
|
+
raise 'invalid request' if data.length != 3
|
23
|
+
req = self.new
|
24
|
+
req.req_method = data[0]
|
25
|
+
req.path = data[1]
|
26
|
+
req.protocol = data[2]
|
27
|
+
return req
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
self.path = '/' if path.nil? || path.empty?
|
32
|
+
"#{req_method} #{path} #{protocol}\n"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class UDPRest::UHTTPResponse
|
37
|
+
attr_accessor :code
|
38
|
+
attr_accessor :protocol
|
39
|
+
attr_accessor :text
|
40
|
+
|
41
|
+
def initialize(code, options = {})
|
42
|
+
self.code = code.to_i
|
43
|
+
self.protocol = options[:protocol] || 'UHTTP/1.0'
|
44
|
+
self.text = options[:text] || ''
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.parse(s)
|
48
|
+
data = s.split("\n\n")
|
49
|
+
status = data[0].split(' ')
|
50
|
+
text = data[1] if data.length > 1
|
51
|
+
self.new(status[1], :text => text || '')
|
52
|
+
end
|
53
|
+
|
54
|
+
def ok?
|
55
|
+
code == 200
|
56
|
+
end
|
57
|
+
|
58
|
+
def status_text
|
59
|
+
return 'OK' if ok?
|
60
|
+
return 'FAILED'
|
61
|
+
end
|
62
|
+
|
63
|
+
def status_line
|
64
|
+
"#{protocol} #{code} #{status_text}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s
|
68
|
+
"#{status_line}\n\n#{text}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Helper for running threads in the background, with a timeout
|
2
|
+
# and error logging.
|
3
|
+
#
|
4
|
+
# Example:
|
5
|
+
#
|
6
|
+
# WorkerThread.new.start :timeout => 5.minutes do
|
7
|
+
# # long running task here...
|
8
|
+
# sleep 10.0
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
class WorkerThread
|
12
|
+
|
13
|
+
def start(options = nil)
|
14
|
+
raise 'background_task needs a block' unless block_given?
|
15
|
+
|
16
|
+
options ||= {}
|
17
|
+
|
18
|
+
worker = Thread.new do
|
19
|
+
begin
|
20
|
+
yield
|
21
|
+
rescue => e
|
22
|
+
$stderr.puts "#{Time.now}\t#{e.class.to_s}\t#{e.message}\n"
|
23
|
+
raise e
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# if the user set a timeout then we need a thread to monitor
|
28
|
+
# the worker to make sure it doesn't run too long
|
29
|
+
if !options[:timeout].nil?
|
30
|
+
Thread.new do
|
31
|
+
sleep options[:timeout].to_f
|
32
|
+
|
33
|
+
if worker.status != false
|
34
|
+
#$stderr.puts "#{Time.now}\tbackground_task thread timeout\n"
|
35
|
+
worker.kill
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
worker
|
41
|
+
end
|
42
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# REST over UDP
|
2
|
+
|
3
|
+
- Most REST requets are very small
|
4
|
+
- it should be possible to implement a simple version of HTTP that can run over UDP in order to make REST requets
|
5
|
+
- we have implemented that
|
6
|
+
- the max packet size is 512 bytes
|
7
|
+
- This gem makes it easy to create servers and clients for udp-rest
|
8
|
+
- it also contains a curl-like command line app
|
9
|
+
- obviously this is not going to work from any browser, but it can be useful for simple command line apps.
|
10
|
+
|
11
|
+
## Try it out
|
12
|
+
|
13
|
+
There is a udp rest server running on uhttp.reednj.com. You can make requests to it by installing the gem.
|
14
|
+
|
15
|
+
gem install udp_rest
|
16
|
+
udp-rest uhttp.reednj.com
|
17
|
+
|
18
|
+
<SCREEN SHOT OF CONSOLE>
|
19
|
+
|
20
|
+
## Server
|
21
|
+
|
22
|
+
Use this gem to create sinatra style servers to respond to requests.
|
23
|
+
|
24
|
+
<CODE>
|
25
|
+
|
26
|
+
## Client
|
27
|
+
|
28
|
+
## Benchmarks
|
29
|
+
|
30
|
+
- do some testing of the latency here, see if it really is faster. Pick a few different servers
|
31
|
+
|
32
|
+
## Other Points
|
33
|
+
|
34
|
+
- encoding is always UTF-8
|
35
|
+
- the max request and response size is 512 bytes
|
data/udp_rest.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'udp_rest/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "udp_rest"
|
8
|
+
spec.version = UDPRest::VERSION
|
9
|
+
spec.authors = ["Nathan Reed"]
|
10
|
+
spec.email = ["reednj@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Client and server modules to allow making REST HTTP requests over UDP}
|
13
|
+
spec.homepage = "https://github.com/reednj/udp_rest"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>=1.9.3'
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
|
25
|
+
spec.add_dependency 'colorize'
|
26
|
+
spec.add_dependency 'trollop'
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: udp_rest
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nathan Reed
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: trollop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- reednj@gmail.com
|
72
|
+
executables:
|
73
|
+
- udp-rest
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- LICENSE.txt
|
81
|
+
- Rakefile
|
82
|
+
- bin/console
|
83
|
+
- bin/setup
|
84
|
+
- demo/simple_server.rb
|
85
|
+
- exe/udp-rest
|
86
|
+
- lib/rest_client.rb
|
87
|
+
- lib/udp_rest.rb
|
88
|
+
- lib/udp_rest/udp.rb
|
89
|
+
- lib/udp_rest/uhttp.rb
|
90
|
+
- lib/udp_rest/version.rb
|
91
|
+
- lib/worker_thread.rb
|
92
|
+
- readme.md
|
93
|
+
- udp_rest.gemspec
|
94
|
+
homepage: https://github.com/reednj/udp_rest
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.9.3
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.6.6
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Client and server modules to allow making REST HTTP requests over UDP
|
118
|
+
test_files: []
|