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.
@@ -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 = '/' + klass.name.downcase
34
- NetworkFacade.log(:debug, "#{klass} is bound to #{@@klass[klass]}")
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
- @uri ||= @options[:uri] || @@klass[self.class] ||
42
- URI::Generic.new('nf', nil, nil, nil, nil, '/' + self.class.name.downcase, nil, nil, nil)
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
- data = Marshal.dump([@uri.path[1..-1], name, args])
55
- size = [data.size].pack('N')
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
- size = client.read(4)
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
- result = Marshal.dump(result)
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
@@ -1,6 +1,6 @@
1
1
  module NetworkFacade
2
2
  NAME = 'Network-Facade'
3
- VERSION = '0.1'
3
+ VERSION = '0.2'
4
4
  COPYRIGHT = 'Copyright (C) 2007 Florent Solt'
5
5
  DESC = 'Object-oriented netwotk facade'
6
6
  AUTHOR = 'Florent Solt'
@@ -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
@@ -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.first
17
+ case ARGV.shift
17
18
  #=======================<client>==============================#
18
19
  when 'client-tcp-uri'
19
- class Foo < NetworkFacade::Client 'nf://backoffice:5042/?hu=dtc'
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 => 'dev', :port => 5042)
27
- p f.bar
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
- class Foo < NetworkFacade::SSL::Client 'nf://installclick:5044'
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.first
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.1"
7
- date: 2007-05-02 00:00:00 +02:00
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