network-facade 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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