rflow-components-http 0.0.2
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.
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/Rakefile +15 -0
- data/lib/rflow/components/http/client.rb +0 -0
- data/lib/rflow/components/http/extensions.rb +68 -0
- data/lib/rflow/components/http/server.rb +123 -0
- data/lib/rflow/components/http/version.rb +7 -0
- data/lib/rflow/components/http.rb +34 -0
- data/lib/rflow-components-http.rb +2 -0
- data/rflow-components-http.gemspec +28 -0
- data/schema/http_request.avsc +19 -0
- data/schema/http_response.avsc +18 -0
- data/spec/extensions_spec.rb +43 -0
- data/spec/schema_spec.rb +67 -0
- data/spec/spec_helper.rb +18 -0
- metadata +128 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rdoc/task'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
|
+
t.verbose = true
|
8
|
+
t.rspec_opts = '--tty --color'
|
9
|
+
end
|
10
|
+
|
11
|
+
Rake::RDocTask.new do |rd|
|
12
|
+
rd.main = "README"
|
13
|
+
rd.rdoc_files.include("README", "lib/**/*.rb")
|
14
|
+
rd.rdoc_dir = File.join('doc', 'html')
|
15
|
+
end
|
File without changes
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class RFlow
|
2
|
+
module Components
|
3
|
+
module HTTP
|
4
|
+
|
5
|
+
# The set of extensions to add capability to HTTP data types
|
6
|
+
module Extensions
|
7
|
+
|
8
|
+
module IPConnectionExtension
|
9
|
+
# Default accessors
|
10
|
+
# TODO: validate the stuffs
|
11
|
+
['client_ip', 'client_port', 'server_ip', 'server_port'].each do |name|
|
12
|
+
define_method name do |*args|
|
13
|
+
data_object[name]
|
14
|
+
end
|
15
|
+
define_method :"#{name}=" do |*args|
|
16
|
+
data_object[name] = args.first
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Need to be careful when extending to not clobber data already in data_object
|
22
|
+
module HTTPRequestExtension
|
23
|
+
def self.extended(base_data)
|
24
|
+
base_data.data_object ||= {'uri' => '/', 'method' => 'GET', 'protocol' => 'HTTP/1.0', 'headers'=>{}, 'content' => ''}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Default accessors
|
28
|
+
['method', 'uri', 'query_string', 'protocol', 'headers', 'content'].each do |name|
|
29
|
+
define_method name do |*args|
|
30
|
+
data_object[name]
|
31
|
+
end
|
32
|
+
define_method :"#{name}=" do |*args|
|
33
|
+
data_object[name] = args.first
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Need to be careful when extending to not clobber data already in data_object
|
39
|
+
module HTTPResponseExtension
|
40
|
+
def self.extended(base_data)
|
41
|
+
base_data.data_object ||= {'protocol' => 'HTTP/1.0', 'status_code' => 200, 'status_reason_phrase' => 'OK', 'headers' => {}, 'content' => ''}
|
42
|
+
end
|
43
|
+
|
44
|
+
# Default accessors
|
45
|
+
['protocol', 'status_reason_phrase', 'headers', 'content'].each do |name|
|
46
|
+
define_method name do |*args|
|
47
|
+
data_object[name]
|
48
|
+
end
|
49
|
+
define_method :"#{name}=" do |*args|
|
50
|
+
data_object[name] = args.first
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
['status_code'].each do |name|
|
55
|
+
define_method name do |*args|
|
56
|
+
data_object[name]
|
57
|
+
end
|
58
|
+
define_method :"#{name}=" do |*args|
|
59
|
+
data_object[name] = args.first.to_i
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'evma_httpserver'
|
3
|
+
|
4
|
+
require 'rflow'
|
5
|
+
|
6
|
+
class RFlow
|
7
|
+
module Components
|
8
|
+
module HTTP
|
9
|
+
|
10
|
+
class Server < RFlow::Component
|
11
|
+
input_port :response_port
|
12
|
+
output_port :request_port
|
13
|
+
|
14
|
+
attr_accessor :port, :listen, :server_signature, :connections
|
15
|
+
|
16
|
+
def configure!(config)
|
17
|
+
@listen = config['listen'] ? config['listen'] : '127.0.0.1'
|
18
|
+
@port = config['port'] ? config['port'].to_i : 8000
|
19
|
+
@connections = Hash.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def run!
|
23
|
+
@server_signature = EM.start_server(@listen, @port, Connection) do |conn|
|
24
|
+
conn.server = self
|
25
|
+
self.connections[conn.signature.to_s] = conn
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Getting all messages to response_port, which we need to filter for
|
30
|
+
# those that pertain to this component and have active connections.
|
31
|
+
# This is done by inspecting the provenance, specifically the
|
32
|
+
# context attribute that we stored originally
|
33
|
+
def process_message(input_port, input_port_key, connection, message)
|
34
|
+
RFlow.logger.debug "Received a message"
|
35
|
+
return unless message.data_type_name == 'RFlow::Message::Data::HTTP::Response'
|
36
|
+
|
37
|
+
|
38
|
+
RFlow.logger.debug "Received a HTTP::Response message, determining if its mine"
|
39
|
+
my_events = message.provenance.find_all {|processing_event| processing_event.component_instance_uuid == instance_uuid}
|
40
|
+
RFlow.logger.debug "Found #{my_events.size} processing events from me"
|
41
|
+
# Attempt to send the data to each context match
|
42
|
+
my_events.each do |processing_event|
|
43
|
+
RFlow.logger.debug "Inspecting #{processing_event.context}"
|
44
|
+
connection_signature = processing_event.context
|
45
|
+
if connections[connection_signature]
|
46
|
+
RFlow.logger.debug "Found connection for #{processing_event.context}"
|
47
|
+
connections[connection_signature].send_http_response message
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Connection < EventMachine::Connection
|
53
|
+
include EventMachine::HttpServer
|
54
|
+
|
55
|
+
attr_accessor :server
|
56
|
+
attr_reader :client_ip, :client_port, :server_ip, :server_port
|
57
|
+
|
58
|
+
def post_init
|
59
|
+
@client_port, @client_ip = Socket.unpack_sockaddr_in(get_peername) rescue ["?", "?.?.?.?"]
|
60
|
+
@server_port, @server_ip = Socket.unpack_sockaddr_in(get_sockname) rescue ["?", "?.?.?.?"]
|
61
|
+
RFlow.logger.debug "Connection from #{@client_ip}:#{@client_port} to #{@server_ip}:#{@server_port}"
|
62
|
+
super
|
63
|
+
no_environment_strings
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def receive_data(data)
|
68
|
+
RFlow.logger.debug "Received #{data.bytesize} bytes of data from #{client_ip}:#{client_port} to #{@server_ip}:#{@server_port}"
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def process_http_request
|
74
|
+
RFlow.logger.debug "Received a HTTP request from #{client_ip}:#{client_port} to #{@server_ip}:#{@server_port}"
|
75
|
+
|
76
|
+
processing_event = RFlow::Message::ProcessingEvent.new(server.instance_uuid, Time.now.utc)
|
77
|
+
|
78
|
+
request_message = RFlow::Message.new('RFlow::Message::Data::HTTP::Request')
|
79
|
+
request_message.data.uri = @http_request_uri
|
80
|
+
|
81
|
+
processing_event.context = signature
|
82
|
+
processing_event.completed_at = Time.now.utc
|
83
|
+
request_message.provenance << processing_event
|
84
|
+
|
85
|
+
server.request_port.send_message request_message
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
def send_http_response(response_message=nil)
|
90
|
+
RFlow.logger.debug "Sending an HTTP response to #{client_ip}:#{client_port}"
|
91
|
+
resp = EventMachine::DelegatedHttpResponse.new(self)
|
92
|
+
|
93
|
+
# Default values
|
94
|
+
resp.status = 200
|
95
|
+
resp.content = ""
|
96
|
+
resp.headers["Content-Type"] = "text/html"
|
97
|
+
resp.headers["Server"] = "Apache"
|
98
|
+
|
99
|
+
if response_message
|
100
|
+
resp.status = response_message.data.status_code
|
101
|
+
resp.content = response_message.data.content
|
102
|
+
response_message.data.headers.each do |header, value|
|
103
|
+
resp[headers] = value
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
resp.send_response
|
108
|
+
close_connection_after_writing
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
# Called when a connection is torn down for whatever reason.
|
113
|
+
# Remove this connection from the server's list
|
114
|
+
def unbind(reason=nil)
|
115
|
+
RFlow.logger.debug "Disconnected from HTTP client #{client_ip}:#{client_port} due to '#{reason}'"
|
116
|
+
server.connections.delete(self.signature)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rflow/components/http/extensions'
|
2
|
+
require 'rflow/components/http/server'
|
3
|
+
|
4
|
+
class RFlow
|
5
|
+
module Components
|
6
|
+
module HTTP
|
7
|
+
# Load the schemas
|
8
|
+
SCHEMA_DIRECTORY = ::File.expand_path(::File.join(::File.dirname(__FILE__), '..', '..', '..', 'schema'))
|
9
|
+
|
10
|
+
SCHEMA_FILES = {
|
11
|
+
'http_response.avsc' => 'RFlow::Message::Data::HTTP::Response',
|
12
|
+
'http_request.avsc' => 'RFlow::Message::Data::HTTP::Request',
|
13
|
+
}
|
14
|
+
|
15
|
+
SCHEMA_FILES.each do |file_name, data_type_name|
|
16
|
+
schema_string = ::File.read(::File.join(SCHEMA_DIRECTORY, file_name))
|
17
|
+
RFlow::Configuration.add_available_data_type data_type_name, 'avro', schema_string
|
18
|
+
end
|
19
|
+
|
20
|
+
# Load the data extensions
|
21
|
+
RFlow::Configuration.add_available_data_extension('RFlow::Message::Data::HTTP::Request',
|
22
|
+
RFlow::Components::HTTP::Extensions::IPConnectionExtension)
|
23
|
+
RFlow::Configuration.add_available_data_extension('RFlow::Message::Data::HTTP::Request',
|
24
|
+
RFlow::Components::HTTP::Extensions::HTTPRequestExtension)
|
25
|
+
|
26
|
+
|
27
|
+
RFlow::Configuration.add_available_data_extension('RFlow::Message::Data::HTTP::Response',
|
28
|
+
RFlow::Components::HTTP::Extensions::IPConnectionExtension)
|
29
|
+
RFlow::Configuration.add_available_data_extension('RFlow::Message::Data::HTTP::Response',
|
30
|
+
RFlow::Components::HTTP::Extensions::HTTPResponseExtension)
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rflow/components/http/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rflow-components-http"
|
7
|
+
s.version = RFlow::Components::HTTP::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.required_ruby_version = '~> 1.9'
|
10
|
+
s.authors = ["Michael L. Artz"]
|
11
|
+
s.email = ["michael.artz@redjack.com"]
|
12
|
+
s.homepage = ""
|
13
|
+
s.summary = %q{HTTP client and server components for the RFlow FBP framework}
|
14
|
+
s.description = %q{HTTP client and server components for the RFlow FBP framework. Also includes the necessary HTTP::Request and HTTP::Response message types}
|
15
|
+
|
16
|
+
s.rubyforge_project = "rflow-components-http"
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
|
23
|
+
s.add_dependency 'rflow', '~> 0.0'
|
24
|
+
s.add_dependency 'eventmachine_httpserver', '~> 0.2'
|
25
|
+
|
26
|
+
s.add_development_dependency 'rspec', '~> 2.6'
|
27
|
+
s.add_development_dependency 'rake', '>= 0.8.7'
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"type": "record",
|
3
|
+
"name": "Request",
|
4
|
+
"namespace": "org.rflow.message.data.http",
|
5
|
+
"aliases": [],
|
6
|
+
"fields": [
|
7
|
+
{"name": "client_ip", "type": ["string", "null"]},
|
8
|
+
{"name": "client_port", "type": ["int", "null"]},
|
9
|
+
{"name": "server_ip", "type": ["string", "null"]},
|
10
|
+
{"name": "server_port", "type": ["int", "null"]},
|
11
|
+
|
12
|
+
{"name": "method", "type": "string"},
|
13
|
+
{"name": "uri", "type": "string"},
|
14
|
+
{"name": "query_string", "type": ["string", "null"]},
|
15
|
+
{"name": "protocol", "type": "string"},
|
16
|
+
{"name": "headers", "type": {"type": "map", "values": ["string", "null"]}},
|
17
|
+
{"name": "content", "type": ["bytes", "null"]}
|
18
|
+
]
|
19
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
{
|
2
|
+
"type": "record",
|
3
|
+
"name": "Response",
|
4
|
+
"namespace": "org.rflow.message.data.http",
|
5
|
+
"aliases": [],
|
6
|
+
"fields": [
|
7
|
+
{"name": "client_ip", "type": ["string", "null"]},
|
8
|
+
{"name": "client_port", "type": ["int", "null"]},
|
9
|
+
{"name": "server_ip", "type": ["string", "null"]},
|
10
|
+
{"name": "server_port", "type": ["int", "null"]},
|
11
|
+
|
12
|
+
{"name": "protocol", "type": "string"},
|
13
|
+
{"name": "status_code", "type": "int"},
|
14
|
+
{"name": "status_reason_phrase", "type": "string"},
|
15
|
+
{"name": "headers", "type": {"type": "map", "values": "string"}},
|
16
|
+
{"name": "content", "type": "bytes"}
|
17
|
+
]
|
18
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe RFlow::Components::HTTP::Extensions::HTTPRequestExtension do
|
4
|
+
before(:each) do
|
5
|
+
@schema_string = RFlow::Configuration.available_data_types['RFlow::Message::Data::HTTP::Request']['avro']
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should work" do
|
9
|
+
RFlow::Configuration.available_data_extensions['RFlow::Message::Data::HTTP::Request'].should include(described_class)
|
10
|
+
|
11
|
+
request = RFlow::Message.new('RFlow::Message::Data::HTTP::Request')
|
12
|
+
request.data.uri.should == '/'
|
13
|
+
request.data.method.should == 'GET'
|
14
|
+
request.data.query_string.should == nil
|
15
|
+
request.data.protocol.should == 'HTTP/1.0'
|
16
|
+
request.data.headers.should == {}
|
17
|
+
|
18
|
+
request.data.uri = 'POST'
|
19
|
+
request.data.uri.should == 'POST'
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
describe RFlow::Components::HTTP::Extensions::HTTPResponseExtension do
|
25
|
+
before(:each) do
|
26
|
+
@schema_string = RFlow::Configuration.available_data_types['RFlow::Message::Data::HTTP::Response']['avro']
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should work" do
|
30
|
+
RFlow::Configuration.available_data_extensions['RFlow::Message::Data::HTTP::Response'].should include(described_class)
|
31
|
+
|
32
|
+
response = RFlow::Message.new('RFlow::Message::Data::HTTP::Response')
|
33
|
+
response.data.protocol.should == 'HTTP/1.0'
|
34
|
+
response.data.status_code.should == 200
|
35
|
+
response.data.status_reason_phrase.should == 'OK'
|
36
|
+
response.data.headers.should == {}
|
37
|
+
response.data.content.should == ''
|
38
|
+
|
39
|
+
response.data.status_code = 404
|
40
|
+
response.data.status_code.should == 404
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/schema_spec.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'RFlow::Message::Data::HTTP::Request Avro Schema' do
|
4
|
+
before(:each) do
|
5
|
+
@schema_string = RFlow::Configuration.available_data_types['RFlow::Message::Data::HTTP::Request']['avro']
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should encode and decode an object" do
|
9
|
+
request = {
|
10
|
+
'method' => 'METHOD',
|
11
|
+
'uri' => 'URI',
|
12
|
+
'query_string' => 'QUERYSTRING',
|
13
|
+
'protocol' => 'PROTOCOL',
|
14
|
+
'headers' => {
|
15
|
+
'header1' => 'HEADER1',
|
16
|
+
'header2' => 'HEADER2',
|
17
|
+
},
|
18
|
+
'content' => '',
|
19
|
+
}
|
20
|
+
|
21
|
+
expect {encode_avro(@schema_string, request)}.to_not raise_error
|
22
|
+
avro_encoded_request = encode_avro(@schema_string, request)
|
23
|
+
|
24
|
+
expect {decode_avro(@schema_string, avro_encoded_request)}.to_not raise_error
|
25
|
+
decoded_request = decode_avro(@schema_string, avro_encoded_request)
|
26
|
+
|
27
|
+
decoded_request['method'].should == request['method']
|
28
|
+
decoded_request['uri'].should == request['uri']
|
29
|
+
decoded_request['query_string'].should == request['query_string']
|
30
|
+
decoded_request['protocol'].should == request['protocol']
|
31
|
+
decoded_request['headers'].should == request['headers']
|
32
|
+
decoded_request['content'].should == request['content']
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
describe 'RFlow::Message::Data::HTTP::Response Avro Schema' do
|
38
|
+
before(:each) do
|
39
|
+
@schema_string = RFlow::Configuration.available_data_types['RFlow::Message::Data::HTTP::Response']['avro']
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should encode and decode an object" do
|
43
|
+
response = {
|
44
|
+
'protocol' => 'METHOD',
|
45
|
+
'status_code' => 200,
|
46
|
+
'status_reason_phrase' => 'STATUSREASONPHRASE',
|
47
|
+
'headers' => {
|
48
|
+
'header1' => 'HEADER1',
|
49
|
+
'header2' => 'HEADER2',
|
50
|
+
},
|
51
|
+
'content' => 'CONTENT',
|
52
|
+
}
|
53
|
+
|
54
|
+
expect {encode_avro(@schema_string, response)}.to_not raise_error
|
55
|
+
avro_encoded_response = encode_avro(@schema_string, response)
|
56
|
+
|
57
|
+
expect {decode_avro(@schema_string, avro_encoded_response)}.to_not raise_error
|
58
|
+
decoded_response = decode_avro(@schema_string, avro_encoded_response)
|
59
|
+
|
60
|
+
decoded_response['protocol'].should == response['protocol']
|
61
|
+
decoded_response['status_code'].should == response['status_code']
|
62
|
+
decoded_response['status_reason_phrase'].should == response['status_reason_phrase']
|
63
|
+
decoded_response['headers'].should == response['headers']
|
64
|
+
decoded_response['content'].should == response['content']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'rflow-components-http'))
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
RFlow.logger = Logger.new STDOUT
|
6
|
+
|
7
|
+
def decode_avro(schema_string, serialized_object)
|
8
|
+
schema = Avro::Schema.parse(schema_string)
|
9
|
+
sio = StringIO.new(serialized_object)
|
10
|
+
Avro::IO::DatumReader.new(schema, schema).read Avro::IO::BinaryDecoder.new(sio)
|
11
|
+
end
|
12
|
+
|
13
|
+
def encode_avro(schema_string, object)
|
14
|
+
schema = Avro::Schema.parse(schema_string)
|
15
|
+
sio = StringIO.new
|
16
|
+
Avro::IO::DatumWriter.new(schema).write object, Avro::IO::BinaryEncoder.new(sio)
|
17
|
+
sio.string
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rflow-components-http
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael L. Artz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rflow
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: eventmachine_httpserver
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.2'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.2'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.6'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.6'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.8.7
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.8.7
|
78
|
+
description: HTTP client and server components for the RFlow FBP framework. Also
|
79
|
+
includes the necessary HTTP::Request and HTTP::Response message types
|
80
|
+
email:
|
81
|
+
- michael.artz@redjack.com
|
82
|
+
executables: []
|
83
|
+
extensions: []
|
84
|
+
extra_rdoc_files: []
|
85
|
+
files:
|
86
|
+
- .gitignore
|
87
|
+
- Gemfile
|
88
|
+
- Rakefile
|
89
|
+
- lib/rflow-components-http.rb
|
90
|
+
- lib/rflow/components/http.rb
|
91
|
+
- lib/rflow/components/http/client.rb
|
92
|
+
- lib/rflow/components/http/extensions.rb
|
93
|
+
- lib/rflow/components/http/server.rb
|
94
|
+
- lib/rflow/components/http/version.rb
|
95
|
+
- rflow-components-http.gemspec
|
96
|
+
- schema/http_request.avsc
|
97
|
+
- schema/http_response.avsc
|
98
|
+
- spec/extensions_spec.rb
|
99
|
+
- spec/schema_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
homepage: ''
|
102
|
+
licenses: []
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ~>
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '1.9'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project: rflow-components-http
|
121
|
+
rubygems_version: 1.8.24
|
122
|
+
signing_key:
|
123
|
+
specification_version: 3
|
124
|
+
summary: HTTP client and server components for the RFlow FBP framework
|
125
|
+
test_files:
|
126
|
+
- spec/extensions_spec.rb
|
127
|
+
- spec/schema_spec.rb
|
128
|
+
- spec/spec_helper.rb
|