ethon 0.3.0 → 0.4.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.
@@ -1,4 +1,5 @@
1
1
  require 'ethon/easies/util'
2
+ require 'ethon/easies/queryable'
2
3
 
3
4
  module Ethon
4
5
  module Easies
@@ -8,7 +9,7 @@ module Ethon
8
9
  # It handles multipart forms, too.
9
10
  class Form
10
11
  include Ethon::Easies::Util
11
- attr_accessor :escape
12
+ include Ethon::Easies::Queryable
12
13
 
13
14
  # Return a new Form.
14
15
  #
@@ -61,38 +62,7 @@ module Ethon
61
62
  #
62
63
  # @return [ Boolean ] True if form is multipart, else false.
63
64
  def multipart?
64
- query_pairs.any?{|pair| pair.last.is_a?(Array)}
65
- end
66
-
67
- # Return the query pairs.
68
- #
69
- # @example Return the query pairs.
70
- # form.query_pairs
71
- #
72
- # @return [ Array ] The query pairs.
73
- def query_pairs
74
- @query_pairs ||= build_query_pairs(@params)
75
- end
76
-
77
- # Return the string representation of the form. This makes only
78
- # sense when the form is not multipart.
79
- #
80
- # @example Return string representation.
81
- # form.to_s
82
- #
83
- # @return [ String ] The string representation.
84
- def to_s
85
- query_pairs.map{|pair| pair.map{|e| escape ? CGI::escape(e.to_s) : e }.join("=")}.join('&')
86
- end
87
-
88
- # Return wether there are elements in the form or not.
89
- #
90
- # @example Return if form is empty.
91
- # form.empty?
92
- #
93
- # @return [ Boolean ] True if form is empty, else false.
94
- def empty?
95
- @params.empty?
65
+ query_pairs.any?{|pair| pair.respond_to?(:last) && pair.last.is_a?(Array)}
96
66
  end
97
67
 
98
68
  # Add form elements to libcurl.
@@ -13,6 +13,7 @@ module Ethon
13
13
  def perform
14
14
  @return_code = Curl.easy_perform(handle)
15
15
  complete
16
+ Ethon.logger.debug("ETHON: performed #{self.log_inspect}") if Ethon.logger
16
17
  @return_code
17
18
  end
18
19
 
@@ -1,4 +1,5 @@
1
1
  require 'ethon/easies/util'
2
+ require 'ethon/easies/queryable'
2
3
 
3
4
  module Ethon
4
5
  module Easies
@@ -6,7 +7,7 @@ module Ethon
6
7
  # This class represents http request parameters.
7
8
  class Params
8
9
  include Ethon::Easies::Util
9
- attr_accessor :escape
10
+ include Ethon::Easies::Queryable
10
11
 
11
12
  # Create a new Params.
12
13
  #
@@ -19,36 +20,6 @@ module Ethon
19
20
  def initialize(params)
20
21
  @params = params || {}
21
22
  end
22
-
23
- # Return the string representation of params.
24
- #
25
- # @example Return string representation.
26
- # params.to_s
27
- #
28
- # @return [ String ] The string representation.
29
- def to_s
30
- query_pairs.map{|pair| pair.map{|e| escape ? CGI::escape(e.to_s) : e }.join("=")}.join('&')
31
- end
32
-
33
- # Return the query pairs.
34
- #
35
- # @example Return the query pairs.
36
- # params.query_pairs
37
- #
38
- # @return [ Array ] The query pairs.
39
- def query_pairs
40
- @query_pairs ||= build_query_pairs(@params)
41
- end
42
-
43
- # Return wether there are elements in the params or not.
44
- #
45
- # @example Return if params is empty.
46
- # params.empty?
47
- #
48
- # @return [ Boolean ] True if params is empty, else false.
49
- def empty?
50
- @params.empty?
51
- end
52
23
  end
53
24
  end
54
25
  end
@@ -0,0 +1,100 @@
1
+ module Ethon
2
+ module Easies
3
+
4
+ # This module contains logic about building
5
+ # query parameters for url or form.
6
+ module Queryable
7
+
8
+ # :nodoc:
9
+ def self.included(base)
10
+ base.send(:attr_accessor, :escape)
11
+ end
12
+
13
+ # Return wether there are elements in the form or not.
14
+ #
15
+ # @example Return if form is empty.
16
+ # form.empty?
17
+ #
18
+ # @return [ Boolean ] True if form is empty, else false.
19
+ def empty?
20
+ @params.empty?
21
+ end
22
+
23
+ # Return the string representation of params.
24
+ #
25
+ # @example Return string representation.
26
+ # params.to_s
27
+ #
28
+ # @return [ String ] The string representation.
29
+ def to_s
30
+ query_pairs.map{ |pair|
31
+ return pair if pair.is_a?(String)
32
+
33
+ pair.map{ |e|
34
+ escape ? CGI::escape(e.to_s) : e
35
+ }.join("=")
36
+ }.join('&')
37
+ end
38
+
39
+ # Return the query pairs.
40
+ #
41
+ # @example Return the query pairs.
42
+ # params.query_pairs
43
+ #
44
+ # @return [ Array ] The query pairs.
45
+ def query_pairs
46
+ @query_pairs ||= build_query_pairs(@params)
47
+ end
48
+
49
+ # Return query pairs build from a hash.
50
+ #
51
+ # @example Build query pairs.
52
+ # action.build_query_pairs({:a => 1, :b => 2})
53
+ # #=> [[:a, 1], [:b, 2]]
54
+ #
55
+ # @param [ Hash ] hash The hash to go through.
56
+ #
57
+ # @return [ Array ] The array of query pairs.
58
+ def build_query_pairs(hash)
59
+ return [hash] if hash.is_a?(String)
60
+
61
+ pairs = []
62
+ recursive = Proc.new do |h, prefix|
63
+ h.each_pair do |k,v|
64
+ key = prefix == '' ? k : "#{prefix}[#{k}]"
65
+ case v
66
+ when Hash
67
+ recursive.call(v, key)
68
+ when Array
69
+ v.each { |x| pairs << [key, x] }
70
+ when File, Tempfile
71
+ pairs << [Util.escape_zero_byte(key), file_info(v)]
72
+ else
73
+ pairs << [Util.escape_zero_byte(key), Util.escape_zero_byte(v)]
74
+ end
75
+ end
76
+ end
77
+ recursive.call(hash, '')
78
+ pairs
79
+ end
80
+
81
+ # Return file info for a file.
82
+ #
83
+ # @example Return file info.
84
+ # action.file_info(File.open('fubar', 'r'))
85
+ #
86
+ # @param [ File ] file The file to handle.
87
+ #
88
+ # @return [ Array ] Array of informations.
89
+ def file_info(file)
90
+ filename = File.basename(file.path)
91
+ types = MIME::Types.type_for(filename)
92
+ [
93
+ filename,
94
+ types.empty? ? 'application/octet-stream' : types[0].to_s,
95
+ File.expand_path(file.path)
96
+ ]
97
+ end
98
+ end
99
+ end
100
+ end
@@ -4,54 +4,6 @@ module Ethon
4
4
  # This module contains small helpers.
5
5
  module Util
6
6
 
7
- # Return query pairs build from a hash.
8
- #
9
- # @example Build query pairs.
10
- # action.build_query_pairs({:a => 1, :b => 2})
11
- # #=> [[:a, 1], [:b, 2]]
12
- #
13
- # @param [ Hash ] hash The hash to go through.
14
- #
15
- # @return [ Array ] The array of query pairs.
16
- def build_query_pairs(hash)
17
- pairs = []
18
- recursive = Proc.new do |h, prefix|
19
- h.each_pair do |k,v|
20
- key = prefix == '' ? k : "#{prefix}[#{k}]"
21
- case v
22
- when Hash
23
- recursive.call(v, key)
24
- when Array
25
- v.each { |x| pairs << [key, x] }
26
- when File, Tempfile
27
- pairs << [Util.escape_zero_byte(key), file_info(v)]
28
- else
29
- pairs << [Util.escape_zero_byte(key), Util.escape_zero_byte(v)]
30
- end
31
- end
32
- end
33
- recursive.call(hash, '')
34
- pairs
35
- end
36
-
37
- # Return file info for a file.
38
- #
39
- # @example Return file info.
40
- # action.file_info(File.open('fubar', 'r'))
41
- #
42
- # @param [ File ] file The file to handle.
43
- #
44
- # @return [ Array ] Array of informations.
45
- def file_info(file)
46
- filename = File.basename(file.path)
47
- types = MIME::Types.type_for(filename)
48
- [
49
- filename,
50
- types.empty? ? 'application/octet-stream' : types[0].to_s,
51
- File.expand_path(file.path)
52
- ]
53
- end
54
-
55
7
  # Escapes zero bytes in strings.
56
8
  #
57
9
  # @example Escape zero bytes.
@@ -62,10 +14,12 @@ module Ethon
62
14
  #
63
15
  # @return [ String, Object ] Escaped String if
64
16
  # zero byte found, original object if not.
65
- def self.escape_zero_byte(value)
17
+ def escape_zero_byte(value)
66
18
  return value unless value.to_s.include?(0.chr)
67
19
  value.to_s.gsub(0.chr, '\\\0')
68
20
  end
21
+
22
+ extend self
69
23
  end
70
24
  end
71
25
  end
data/lib/ethon/easy.rb CHANGED
@@ -192,14 +192,32 @@ module Ethon
192
192
  #
193
193
  # @return [ Hash ] The informations hash.
194
194
  def to_hash
195
- hash = {}
196
- hash[:return_code] = return_code
197
- hash[:response_header] = response_header
198
- hash[:response_body] = response_body
195
+ return @hash if defined?(@hash) && @hash
196
+ @hash = {
197
+ :return_code => return_code,
198
+ :response_header => response_header,
199
+ :response_body => response_body
200
+ }
199
201
  Easies::Informations::AVAILABLE_INFORMATIONS.keys.each do |info|
200
- hash[info] = method(info).call
202
+ @hash[info] = method(info).call
201
203
  end
202
- hash
204
+ @hash
205
+ end
206
+
207
+ # Return pretty log out.
208
+ #
209
+ # @example Return log out.
210
+ # easy.log_inspect
211
+ #
212
+ # @return [ String ] The log out.
213
+ def log_inspect
214
+ hash = {
215
+ :url => url,
216
+ :response_code => response_code,
217
+ :return_code => return_code,
218
+ :total_time => total_time
219
+ }
220
+ "EASY #{hash.map{|k, v| "#{k}=#{v}"}.flatten.join(' ')}"
203
221
  end
204
222
  end
205
223
  end
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+ module Ethon
3
+
4
+ # Contains logging behaviour.
5
+ module Loggable
6
+
7
+ # Get the logger.
8
+ #
9
+ # @note Will try to grab Rails' logger first before creating a new logger
10
+ # with stdout.
11
+ #
12
+ # @example Get the logger.
13
+ # Loggable.logger
14
+ #
15
+ # @return [ Logger ] The logger.
16
+ def logger
17
+ return @logger if defined?(@logger)
18
+ @logger = rails_logger || default_logger
19
+ end
20
+
21
+ # Set the logger.
22
+ #
23
+ # @example Set the logger.
24
+ # Loggable.logger = Logger.new($stdout)
25
+ #
26
+ # @param [ Logger ] logger The logger to set.
27
+ #
28
+ # @return [ Logger ] The new logger.
29
+ def logger=(logger)
30
+ @logger = logger
31
+ end
32
+
33
+ private
34
+
35
+ # Gets the default Ethon logger - stdout.
36
+ #
37
+ # @example Get the default logger.
38
+ # Loggable.default_logger
39
+ #
40
+ # @return [ Logger ] The default logger.
41
+ def default_logger
42
+ logger = Logger.new($stdout)
43
+ logger.level = Logger::INFO
44
+ logger
45
+ end
46
+
47
+ # Get the Rails logger if it's defined.
48
+ #
49
+ # @example Get Rails' logger.
50
+ # Loggable.rails_logger
51
+ #
52
+ # @return [ Logger ] The Rails logger.
53
+ def rails_logger
54
+ defined?(::Rails) && ::Rails.respond_to?(:logger) && ::Rails.logger
55
+ end
56
+ end
57
+ extend Loggable
58
+ end
@@ -32,6 +32,7 @@ module Ethon
32
32
  # @example Perform multi.
33
33
  # multi.perform
34
34
  def perform
35
+ Ethon.logger.debug("ETHON: started MULTI") if Ethon.logger
35
36
  while ongoing?
36
37
  run
37
38
  timeout = get_timeout
@@ -39,6 +40,8 @@ module Ethon
39
40
  reset_fds
40
41
  set_fds(timeout)
41
42
  end
43
+ Ethon.logger.debug("ETHON: performed MULTI") if Ethon.logger
44
+ nil
42
45
  end
43
46
 
44
47
  # Get timeout.
@@ -100,6 +103,7 @@ module Ethon
100
103
  easy.return_code = msg[:data][:code]
101
104
  delete(easy)
102
105
  easy.complete
106
+ Ethon.logger.debug("ETHON: performed #{easy.log_inspect}") if Ethon.logger
103
107
  end
104
108
  end
105
109
 
data/lib/ethon/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Ethon
2
2
 
3
3
  # Ethon version.
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/ethon.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'logger'
1
2
  require 'ffi'
2
3
  require 'rbconfig'
3
4
  require 'thread'
@@ -5,11 +6,11 @@ require 'mime/types'
5
6
  require 'cgi'
6
7
  require 'tempfile'
7
8
 
8
- require 'ethon/extensions'
9
9
  require 'ethon/curl'
10
10
  require 'ethon/errors'
11
11
  require 'ethon/easy'
12
12
  require 'ethon/multi'
13
+ require 'ethon/loggable'
13
14
  require 'ethon/version'
14
15
 
15
16
  # Ethon is a very simple libcurl.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ethon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-02 00:00:00.000000000 Z
12
+ date: 2012-07-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -195,6 +195,18 @@ extensions: []
195
195
  extra_rdoc_files: []
196
196
  files:
197
197
  - lib/ethon/curl.rb
198
+ - lib/ethon/curls/auth_types.rb
199
+ - lib/ethon/curls/classes.rb
200
+ - lib/ethon/curls/codes.rb
201
+ - lib/ethon/curls/constants.rb
202
+ - lib/ethon/curls/form_options.rb
203
+ - lib/ethon/curls/functions.rb
204
+ - lib/ethon/curls/infos.rb
205
+ - lib/ethon/curls/messages.rb
206
+ - lib/ethon/curls/options.rb
207
+ - lib/ethon/curls/proxy_types.rb
208
+ - lib/ethon/curls/settings.rb
209
+ - lib/ethon/curls/ssl_versions.rb
198
210
  - lib/ethon/easies/callbacks.rb
199
211
  - lib/ethon/easies/form.rb
200
212
  - lib/ethon/easies/header.rb
@@ -213,6 +225,7 @@ files:
213
225
  - lib/ethon/easies/operations.rb
214
226
  - lib/ethon/easies/options.rb
215
227
  - lib/ethon/easies/params.rb
228
+ - lib/ethon/easies/queryable.rb
216
229
  - lib/ethon/easies/response_callbacks.rb
217
230
  - lib/ethon/easies/util.rb
218
231
  - lib/ethon/easy.rb
@@ -226,8 +239,7 @@ files:
226
239
  - lib/ethon/errors/multi_timeout.rb
227
240
  - lib/ethon/errors/select.rb
228
241
  - lib/ethon/errors.rb
229
- - lib/ethon/extensions/string.rb
230
- - lib/ethon/extensions.rb
242
+ - lib/ethon/loggable.rb
231
243
  - lib/ethon/multi.rb
232
244
  - lib/ethon/multies/operations.rb
233
245
  - lib/ethon/multies/stack.rb
@@ -252,7 +264,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
252
264
  version: '0'
253
265
  segments:
254
266
  - 0
255
- hash: 1054475577707452411
267
+ hash: 2336974979301889597
256
268
  required_rubygems_version: !ruby/object:Gem::Requirement
257
269
  none: false
258
270
  requirements:
@@ -1,40 +0,0 @@
1
- module Ethon
2
-
3
- # This module contains all core extensions ethon
4
- # needs.
5
- module Extensions
6
- module String # :nodoc:
7
-
8
- unless ''.respond_to?(:byteslice)
9
- # Return part of the string.
10
- #
11
- # @return [ String ] Part of the string.
12
- def byteslice(*args)
13
- self[*args]
14
- end
15
- end
16
-
17
- # Convert string to underscore. Taken from
18
- # activesupport, renamed in order to no collide
19
- # with it.
20
- #
21
- # @example Underscore.
22
- # "ClassName".underscr
23
- # #=> "class_name"
24
- #
25
- # @return [ String ] Underscore string.
26
- def underscr
27
- word = self.dup
28
- word.gsub!('::', '_')
29
- word.gsub!(/(?:([A-Za-z\d])|^)(#{/(?=a)b/})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
30
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
31
- word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
32
- word.tr!("-", "_")
33
- word.downcase!
34
- word
35
- end
36
- end
37
- end
38
- end
39
-
40
- ::String.__send__(:include, Ethon::Extensions::String)
@@ -1 +0,0 @@
1
- require 'ethon/extensions/string.rb'