network-facade 0.1 → 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/lib/network-facade/base.rb +54 -18
- data/lib/network-facade/config.rb +1 -1
- data/lib/network-facade/rest.rb +119 -0
- data/lib/network-facade.rb +70 -6
- metadata +3 -2
data/lib/network-facade/base.rb
CHANGED
@@ -30,34 +30,36 @@ module Base
|
|
30
30
|
@@klass ||= {}
|
31
31
|
if defined? @@uri and not @@uri.nil?
|
32
32
|
@@klass[klass] = URI.parse(@@uri)
|
33
|
-
@@klass[klass].path
|
34
|
-
|
33
|
+
if @@klass[klass].path.empty? or @@klass[klass].path == '/'
|
34
|
+
@@klass[klass].path = '/' + klass.name.downcase
|
35
|
+
end
|
35
36
|
end
|
36
37
|
@@uri = nil
|
37
38
|
end
|
38
39
|
|
39
40
|
def initialize(options = {})
|
40
41
|
@options = options
|
41
|
-
|
42
|
-
URI
|
42
|
+
if @options[:uri]
|
43
|
+
@uri ||= URI.parse(@options[:uri])
|
44
|
+
elsif @@klass[self.class]
|
45
|
+
@uri ||= @@klass[self.class]
|
46
|
+
else
|
47
|
+
@uri ||= URI::Generic.new('nf', nil, nil, nil, nil, '/' + self.class.name.downcase, nil, nil, nil)
|
48
|
+
end
|
43
49
|
@uri.host = @options[:host] if @options[:host]
|
44
50
|
@uri.port = @options[:port] if @options[:port]
|
45
51
|
@uri.path = @options[:path] if @options[:path]
|
46
52
|
@uri.query = @options[:query] if @options[:query]
|
47
53
|
@uri.userinfo = @options[:userinfo] if @options[:userinfo]
|
48
54
|
@mutex = Mutex.new
|
55
|
+
require 'zlib' if @options[:compress]
|
49
56
|
end
|
50
57
|
|
51
58
|
def method_missing(name, *args)
|
52
59
|
NetworkFacade.log(:debug, "Method called with #{args.inspect}", "#{self.class}##{name}")
|
53
60
|
begin
|
54
|
-
|
55
|
-
|
56
|
-
@client.write(size)
|
57
|
-
@client.write(data)
|
58
|
-
size = @client.read(4).unpack('N').first
|
59
|
-
data = @client.read(size)
|
60
|
-
result = Marshal.load(data)
|
61
|
+
__write__([@uri.path[1..-1], name, args])
|
62
|
+
result = __read__
|
61
63
|
if result.is_a? Exception
|
62
64
|
NetworkFacade.log(:info, "Exception occured : #{result.inspect}", "#{self.class}##{name}")
|
63
65
|
result.backtrace.collect! do |line|
|
@@ -72,11 +74,31 @@ module Base
|
|
72
74
|
retry
|
73
75
|
end
|
74
76
|
end
|
77
|
+
|
78
|
+
def __read__
|
79
|
+
size = @client.read(4).unpack('N').first
|
80
|
+
NetworkFacade.log(:debug, "Read #{size + 4} bytes", @uri)
|
81
|
+
data = @client.read(size)
|
82
|
+
data = Zlib::Inflate.inflate(data) if @options[:compress]
|
83
|
+
Marshal.load(data)
|
84
|
+
end
|
85
|
+
|
86
|
+
def __write__(data)
|
87
|
+
data = Marshal.dump(data)
|
88
|
+
data = Zlib::Deflate.deflate(data, Zlib::FINISH) if @options[:compress]
|
89
|
+
NetworkFacade.log(:debug, "Write #{data.size + 4} bytes", @uri)
|
90
|
+
size = [data.size].pack('N')
|
91
|
+
@client.write(size)
|
92
|
+
@client.write(data)
|
93
|
+
@client.flush
|
94
|
+
end
|
95
|
+
|
75
96
|
end
|
76
97
|
|
77
98
|
class Server
|
78
99
|
def initialize(options = {})
|
79
100
|
@options = options
|
101
|
+
require 'zlib' if @options[:compress]
|
80
102
|
@fd = [@options[:server]]
|
81
103
|
@objs = {}
|
82
104
|
end
|
@@ -115,10 +137,7 @@ module Base
|
|
115
137
|
size = nil
|
116
138
|
data = nil
|
117
139
|
begin
|
118
|
-
|
119
|
-
raise EOFError if size.nil?
|
120
|
-
size = size.unpack('N').first
|
121
|
-
data = Marshal.load(client.read(size))
|
140
|
+
data = read(client)
|
122
141
|
result = nil
|
123
142
|
begin
|
124
143
|
if @objs[data[0]].respond_to? data[1]
|
@@ -132,9 +151,7 @@ module Base
|
|
132
151
|
NetworkFacade.log(:info, "Error occured when executing #{data[1].inspect} with #{data[2].inspect}", client_id(client))
|
133
152
|
NetworkFacade.log(:info, $!)
|
134
153
|
end
|
135
|
-
|
136
|
-
client.write([result.size].pack('N'))
|
137
|
-
client.write(result)
|
154
|
+
write(client, result)
|
138
155
|
rescue Exception
|
139
156
|
NetworkFacade.log(:info, "Close connection", client_id(client))
|
140
157
|
client.close
|
@@ -144,6 +161,25 @@ module Base
|
|
144
161
|
end
|
145
162
|
end
|
146
163
|
end
|
164
|
+
|
165
|
+
def read(client)
|
166
|
+
size = client.read(4)
|
167
|
+
raise EOFError if size.nil?
|
168
|
+
size = size.unpack('N').first
|
169
|
+
NetworkFacade.log(:debug, "Read #{size + 4} bytes", client_id(client))
|
170
|
+
data = client.read(size)
|
171
|
+
data = Zlib::Inflate.inflate(data) if @options[:compress]
|
172
|
+
Marshal.load(data)
|
173
|
+
end
|
174
|
+
|
175
|
+
def write(client, data)
|
176
|
+
data = Marshal.dump(data)
|
177
|
+
data = Zlib::Deflate.deflate(data, Zlib::FINISH) if @options[:compress]
|
178
|
+
NetworkFacade.log(:debug, "Write #{data.size + 4} bytes", client_id(client))
|
179
|
+
client.write([data.size].pack('N'))
|
180
|
+
client.write(data)
|
181
|
+
client.flush
|
182
|
+
end
|
147
183
|
end
|
148
184
|
|
149
185
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'cgi'
|
3
|
+
require 'rubygems'
|
4
|
+
begin
|
5
|
+
require 'xml/libxml'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rexml/document'
|
8
|
+
end
|
9
|
+
begin
|
10
|
+
require 'json'
|
11
|
+
rescue
|
12
|
+
# Do nothing
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
module NetworkFacade
|
17
|
+
module REST
|
18
|
+
|
19
|
+
def self.Client(uri = nil)
|
20
|
+
Client.uri = uri
|
21
|
+
Client
|
22
|
+
end
|
23
|
+
|
24
|
+
class Client < Base::Client
|
25
|
+
def initialize(options = {})
|
26
|
+
super
|
27
|
+
@cookies = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(name, *args)
|
31
|
+
|
32
|
+
# Build query string
|
33
|
+
params = args.first || {}
|
34
|
+
raise "Params must be an Hash table" unless params.is_a? Hash
|
35
|
+
qs = params.keys.collect do |k|
|
36
|
+
"#{k}=#{CGI::escape(params[k].to_s)}"
|
37
|
+
end.join('&')
|
38
|
+
|
39
|
+
# Cutom method mapping defined ?
|
40
|
+
if @options[:mapping] and @options[:mapping][name]
|
41
|
+
@uri.path = @options[:mapping][name]
|
42
|
+
end
|
43
|
+
|
44
|
+
format = @options[:append_slash] ? '%s/?%s' : '%s?%s'
|
45
|
+
Net::HTTP.start(@uri.host, @uri.port) do |http|
|
46
|
+
|
47
|
+
# Build header fields
|
48
|
+
header = @options[:header] || {}
|
49
|
+
header['User-Agent'] = @options[:user_agent] || NetworkFacade::NAME + '/' + NetworkFacade::VERSION
|
50
|
+
unless @cookies.empty?
|
51
|
+
header['Cookie'] = @cookies.keys.collect do |k|
|
52
|
+
"#{k}=#{@cookies[k]}"
|
53
|
+
end.join('; ')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Build request path
|
57
|
+
if @options[:method] == :path
|
58
|
+
path = format % [ "#{@uri.path}/#{name}", qs ]
|
59
|
+
elsif @options[:method] == :param and @options[:method_param]
|
60
|
+
path = format % [ @uri.path, "#{qs}&#{@options[:method_param]}=#{CGI::escape(name.to_s)}" ]
|
61
|
+
else
|
62
|
+
path = format % [ @uri.path, qs ]
|
63
|
+
end
|
64
|
+
|
65
|
+
# POST or GET
|
66
|
+
if @options[:post].is_a? Array and @options[:post].include? name
|
67
|
+
req = Net::HTTP::Post.new(path, header)
|
68
|
+
req.form_data = params
|
69
|
+
else
|
70
|
+
req = Net::HTTP::Get.new(path, header)
|
71
|
+
NetworkFacade.log(:info, "GET #{req.path}")
|
72
|
+
end
|
73
|
+
res = http.request(req)
|
74
|
+
|
75
|
+
# Remember cookies
|
76
|
+
CGI::Cookie::parse(res['set-cookie']).each do |k,v|
|
77
|
+
next if k == 'path' or k == 'expires'
|
78
|
+
@cookies[k] = v.value
|
79
|
+
end
|
80
|
+
|
81
|
+
# Return the correct data
|
82
|
+
case res.code
|
83
|
+
when '200'
|
84
|
+
case res.content_type
|
85
|
+
when /xml/
|
86
|
+
if defined? XML
|
87
|
+
parser = XML::Parser.new
|
88
|
+
parser.string = res.body
|
89
|
+
data = parser.parse
|
90
|
+
else
|
91
|
+
data = REXML::Document.new(res.body)
|
92
|
+
end
|
93
|
+
when /json/
|
94
|
+
if defined? JSON
|
95
|
+
data = JSON.parse res.body
|
96
|
+
else
|
97
|
+
data = res.body
|
98
|
+
end
|
99
|
+
when /php/
|
100
|
+
#TODO: http://php.net/serialize, http://hurring.com/code/perl/serialize/
|
101
|
+
raise "Not implemented yet"
|
102
|
+
else
|
103
|
+
data = res.body
|
104
|
+
end
|
105
|
+
when /3\d\d/
|
106
|
+
# FIXME
|
107
|
+
raise "Redirection not supported yet"
|
108
|
+
else
|
109
|
+
NetworkFacade.log(:error, "An error occured when calling #{name} (returned code = #{res.code})")
|
110
|
+
end
|
111
|
+
|
112
|
+
# Return the header if asked
|
113
|
+
@options[:header] ? [res.to_hash, data] : data
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
data/lib/network-facade.rb
CHANGED
@@ -8,49 +8,113 @@ require 'network-facade/base'
|
|
8
8
|
require 'network-facade/tcp'
|
9
9
|
require 'network-facade/unix'
|
10
10
|
require 'network-facade/ssl'
|
11
|
+
require 'network-facade/rest'
|
11
12
|
require 'network-facade/defaults'
|
12
13
|
|
13
14
|
if __FILE__ == $0
|
14
15
|
NetworkFacade.log = STDERR
|
15
16
|
|
16
|
-
case ARGV.
|
17
|
+
case ARGV.shift
|
17
18
|
#=======================<client>==============================#
|
18
19
|
when 'client-tcp-uri'
|
19
|
-
|
20
|
+
|
21
|
+
class Foo < NetworkFacade::Client 'nf://localhost:5042'
|
20
22
|
end
|
21
23
|
f = Foo.new
|
22
24
|
p f.bar
|
25
|
+
|
23
26
|
when 'client-tcp-class'
|
27
|
+
|
24
28
|
class Foo < NetworkFacade::Client
|
25
29
|
end
|
26
|
-
f = Foo.new(:host => '
|
27
|
-
p f.
|
30
|
+
f = Foo.new(:host => 'localhost', :port => 5042)
|
31
|
+
p f.big
|
32
|
+
|
28
33
|
when 'client-unix'
|
34
|
+
|
29
35
|
class Foo < NetworkFacade::Unix::Client
|
30
36
|
end
|
31
37
|
f = Foo.new
|
32
38
|
p f.bar
|
39
|
+
|
33
40
|
when 'client-ssl'
|
34
|
-
|
41
|
+
|
42
|
+
class Foo < NetworkFacade::SSL::Client 'nf://localhost:5044'
|
35
43
|
end
|
36
44
|
f = Foo.new(:ca => '../cert/ca.cert',
|
37
45
|
:cert => '../cert/client.cert',
|
38
46
|
:key => '../cert/client.key')
|
39
47
|
p f.bar
|
48
|
+
|
49
|
+
when 'client-tcp-compress'
|
50
|
+
|
51
|
+
class Foo < NetworkFacade::Client
|
52
|
+
end
|
53
|
+
p Foo.new(:compress => true).big
|
54
|
+
|
55
|
+
when 'client-rest-rtm'
|
56
|
+
|
57
|
+
class Foo < NetworkFacade::REST::Client 'http://www.rememberthemilk.com/services/rest/'
|
58
|
+
end
|
59
|
+
|
60
|
+
f = Foo.new
|
61
|
+
p f.call(:method => 'rtm.test.echo', :api_key => ARGV.first, :foo => 'bar')
|
62
|
+
|
63
|
+
f = Foo.new(:method => :param, :method_param => 'method')
|
64
|
+
p f.send('rtm.test.echo', :api_key => ARGV.first, :foo => 'bar')
|
65
|
+
|
66
|
+
when 'client-rest-netvibes'
|
67
|
+
|
68
|
+
class Foo < NetworkFacade::REST::Client 'http://www.netvibes.com'
|
69
|
+
end
|
70
|
+
f = Foo.new(:mapping => {
|
71
|
+
:login => '/user/signIn.php',
|
72
|
+
:load => '/get/userData.php',
|
73
|
+
:save => '/save/userData.php'
|
74
|
+
}, :post => [:login, :save])
|
75
|
+
|
76
|
+
p f.login(:email => 'paillerosse@lescampeurs.org', :password => ARGV.first)
|
77
|
+
p f.load
|
78
|
+
|
79
|
+
when 'client-rest-flickr'
|
80
|
+
|
81
|
+
class Foo < NetworkFacade::REST::Client 'http://api.flickr.com/services/rest/'
|
82
|
+
end
|
83
|
+
|
84
|
+
f = Foo.new
|
85
|
+
p f.call(:method => 'flickr.test.echo', :api_key => ARGV.first, :foo => 'bar')
|
86
|
+
|
87
|
+
when 'client-rest-digg'
|
88
|
+
|
89
|
+
class Foo < NetworkFacade::REST::Client 'http://services.digg.com'
|
90
|
+
end
|
91
|
+
f = Foo.new(:mapping => {
|
92
|
+
:apple_stories => '/stories/topic/apple',
|
93
|
+
:me => '/user/pyros'
|
94
|
+
})
|
95
|
+
p f.apple_stories(:appkey => 'http://network-facade.rubyforge.org', :count => 3)
|
96
|
+
p f.apple_stories(:appkey => 'http://network-facade.rubyforge.org', :count => 3, :type => :json)
|
97
|
+
p f.me(:appkey => 'http://network-facade.rubyforge.org')
|
98
|
+
|
40
99
|
#=======================</client>=============================#
|
41
100
|
else
|
42
101
|
class Foo
|
43
102
|
def bar
|
44
103
|
42
|
45
104
|
end
|
105
|
+
def big
|
106
|
+
(Time.now.to_s + "\n") * 10
|
107
|
+
end
|
46
108
|
def error
|
47
109
|
raise "Error"
|
48
110
|
end
|
49
111
|
end
|
50
|
-
case ARGV.
|
112
|
+
case ARGV.shift
|
51
113
|
#=======================<server>==============================#
|
52
114
|
when 'server-tcp'
|
53
115
|
NetworkFacade::Server.new.add(Foo.new).start
|
116
|
+
when 'server-tcp-compress'
|
117
|
+
NetworkFacade::Server.new(:compress => true).add(Foo.new).start
|
54
118
|
when 'server-unix'
|
55
119
|
NetworkFacade::Unix::Server.new.add(Foo.new).start
|
56
120
|
when 'server-ssl'
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: network-facade
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2007-05-
|
6
|
+
version: "0.2"
|
7
|
+
date: 2007-05-03 00:00:00 +02:00
|
8
8
|
summary: Object-oriented netwotk facade
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- lib/network-facade/base.rb
|
36
36
|
- lib/network-facade/defaults.rb
|
37
37
|
- lib/network-facade/ssl.rb
|
38
|
+
- lib/network-facade/rest.rb
|
38
39
|
- lib/network-facade.rb
|
39
40
|
test_files: []
|
40
41
|
|