astrotrain 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Gemfile +8 -0
  2. data/LICENSE +18 -17
  3. data/Rakefile +118 -103
  4. data/astrotrain.gemspec +87 -136
  5. data/lib/astrotrain.rb +47 -51
  6. data/lib/astrotrain/attachment.rb +55 -0
  7. data/lib/astrotrain/message.rb +221 -235
  8. data/lib/astrotrain/transports/http_post.rb +67 -0
  9. data/lib/astrotrain/transports/resque.rb +63 -0
  10. data/test/fixtures/bad_email_format.txt +15 -0
  11. data/test/fixtures/basic.txt +4 -1
  12. data/test/fixtures/iso-8859-1.txt +1 -0
  13. data/test/message_test.rb +146 -457
  14. data/test/test_helper.rb +20 -42
  15. data/test/transport_test.rb +98 -100
  16. metadata +100 -243
  17. data/.gitignore +0 -26
  18. data/README +0 -47
  19. data/VERSION +0 -1
  20. data/config/sample.rb +0 -12
  21. data/lib/astrotrain/api.rb +0 -52
  22. data/lib/astrotrain/logged_mail.rb +0 -48
  23. data/lib/astrotrain/mapping.rb +0 -162
  24. data/lib/astrotrain/mapping/http_post.rb +0 -18
  25. data/lib/astrotrain/mapping/jabber.rb +0 -28
  26. data/lib/astrotrain/mapping/transport.rb +0 -55
  27. data/lib/astrotrain/tmail.rb +0 -58
  28. data/lib/astrotrain/worker.rb +0 -65
  29. data/lib/vendor/rest-client/README.rdoc +0 -104
  30. data/lib/vendor/rest-client/Rakefile +0 -84
  31. data/lib/vendor/rest-client/bin/restclient +0 -65
  32. data/lib/vendor/rest-client/foo.diff +0 -66
  33. data/lib/vendor/rest-client/lib/rest_client.rb +0 -188
  34. data/lib/vendor/rest-client/lib/rest_client/net_http_ext.rb +0 -23
  35. data/lib/vendor/rest-client/lib/rest_client/payload.rb +0 -185
  36. data/lib/vendor/rest-client/lib/rest_client/request_errors.rb +0 -75
  37. data/lib/vendor/rest-client/lib/rest_client/resource.rb +0 -103
  38. data/lib/vendor/rest-client/rest-client.gemspec +0 -18
  39. data/lib/vendor/rest-client/spec/base.rb +0 -5
  40. data/lib/vendor/rest-client/spec/master_shake.jpg +0 -0
  41. data/lib/vendor/rest-client/spec/payload_spec.rb +0 -71
  42. data/lib/vendor/rest-client/spec/request_errors_spec.rb +0 -44
  43. data/lib/vendor/rest-client/spec/resource_spec.rb +0 -52
  44. data/lib/vendor/rest-client/spec/rest_client_spec.rb +0 -219
  45. data/test/api_test.rb +0 -32
  46. data/test/logged_mail_test.rb +0 -67
  47. data/test/mapping_test.rb +0 -129
@@ -1,188 +0,0 @@
1
- require 'uri'
2
- require 'net/https'
3
-
4
- require File.dirname(__FILE__) + '/rest_client/resource'
5
- require File.dirname(__FILE__) + '/rest_client/request_errors'
6
- require File.dirname(__FILE__) + '/rest_client/payload'
7
- require File.dirname(__FILE__) + '/rest_client/net_http_ext'
8
-
9
- # This module's static methods are the entry point for using the REST client.
10
- #
11
- # # GET
12
- # xml = RestClient.get 'http://example.com/resource'
13
- # jpg = RestClient.get 'http://example.com/resource', :accept => 'image/jpg'
14
- #
15
- # # authentication and SSL
16
- # RestClient.get 'https://user:password@example.com/private/resource'
17
- #
18
- # # POST or PUT with a hash sends parameters as a urlencoded form body
19
- # RestClient.post 'http://example.com/resource', :param1 => 'one'
20
- #
21
- # # nest hash parameters
22
- # RestClient.post 'http://example.com/resource', :nested => { :param1 => 'one' }
23
- #
24
- # # POST and PUT with raw payloads
25
- # RestClient.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
26
- # RestClient.post 'http://example.com/resource.xml', xml_doc
27
- # RestClient.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
28
- #
29
- # # DELETE
30
- # RestClient.delete 'http://example.com/resource'
31
- #
32
- # For live tests of RestClient, try using http://rest-test.heroku.com, which echoes back information about the rest call:
33
- #
34
- # >> RestClient.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
35
- # => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
36
- #
37
- module RestClient
38
- def self.get(url, headers={}, &b)
39
- Request.execute(:method => :get,
40
- :url => url,
41
- :headers => headers, &b)
42
- end
43
-
44
- def self.post(url, payload, headers={}, &b)
45
- Request.execute(:method => :post,
46
- :url => url,
47
- :payload => payload,
48
- :headers => headers, &b)
49
- end
50
-
51
- def self.put(url, payload, headers={}, &b)
52
- Request.execute(:method => :put,
53
- :url => url,
54
- :payload => payload,
55
- :headers => headers, &b)
56
- end
57
-
58
- def self.delete(url, headers={}, &b)
59
- Request.execute(:method => :delete,
60
- :url => url,
61
- :headers => headers, &b)
62
- end
63
-
64
- # Internal class used to build and execute the request.
65
- class Request
66
- attr_reader :method, :url, :headers, :user, :password
67
-
68
- def self.execute(args, &b)
69
- new(args).execute(&b)
70
- end
71
-
72
- def initialize(args)
73
- @method = args[:method] or raise ArgumentError, "must pass :method"
74
- @url = args[:url] or raise ArgumentError, "must pass :url"
75
- @payload = Payload.generate(args[:payload] || '')
76
- @headers = args[:headers] || {}
77
- @user = args[:user]
78
- @password = args[:password]
79
- end
80
-
81
- def execute(&b)
82
- execute_inner(&b)
83
- rescue Redirect => e
84
- @url = e.url
85
- execute(&b)
86
- end
87
-
88
- def execute_inner(&b)
89
- uri = parse_url_with_auth(url)
90
- transmit(uri, net_http_class(method).new(uri.request_uri, make_headers(headers)), payload, &b)
91
- end
92
-
93
- def make_headers(user_headers)
94
- final = {}
95
- merged = default_headers.merge(user_headers)
96
- merged.keys.each do |key|
97
- final[key.to_s.gsub(/_/, '-').capitalize] = merged[key]
98
- end
99
- final
100
- end
101
-
102
- def net_http_class(method)
103
- Net::HTTP.const_get(method.to_s.capitalize)
104
- end
105
-
106
- def parse_url(url)
107
- url = "http://#{url}" unless url.match(/^http/)
108
- URI.parse(url)
109
- end
110
-
111
- def parse_url_with_auth(url)
112
- uri = parse_url(url)
113
- @user = uri.user if uri.user
114
- @password = uri.password if uri.password
115
- uri
116
- end
117
-
118
- def process_payload(p=nil, parent_key=nil)
119
- unless p.is_a?(Hash)
120
- p
121
- else
122
- @headers[:content_type] ||= 'application/x-www-form-urlencoded'
123
- p.keys.map do |k|
124
- key = parent_key ? "#{parent_key}[#{k}]" : k
125
- if p[k].is_a? Hash
126
- process_payload(p[k], key)
127
- else
128
- value = URI.escape(p[k].to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
129
- "#{key}=#{value}"
130
- end
131
- end.join("&")
132
- end
133
- end
134
-
135
- def transmit(uri, req, payload, &b)
136
- setup_credentials(req)
137
-
138
- net = Net::HTTP.new(uri.host, uri.port)
139
- net.use_ssl = uri.is_a?(URI::HTTPS)
140
- net.start do |http|
141
- ## Ok. I know this is weird but it's a hack for now
142
- ## this lets process_result determine if it should read the body
143
- ## into memory or not
144
- process_result(http.request(req, payload || "", &b), &b)
145
- end
146
- rescue EOFError
147
- raise RestClient::ServerBrokeConnection
148
- rescue Timeout::Error
149
- raise RestClient::RequestTimeout
150
- ensure
151
- payload.close
152
- end
153
-
154
- def setup_credentials(req)
155
- req.basic_auth(user, password) if user
156
- end
157
-
158
- def process_result(res, &b)
159
- if %w(200 201 202).include? res.code
160
- return res.body unless b
161
- elsif %w(301 302 303).include? res.code
162
- url = res.header['Location']
163
-
164
- if url !~ /^http/
165
- uri = URI.parse(@url)
166
- uri.path = "/#{url}".squeeze('/')
167
- url = uri.to_s
168
- end
169
-
170
- raise Redirect, url
171
- elsif res.code == "401"
172
- raise Unauthorized
173
- elsif res.code == "404"
174
- raise ResourceNotFound
175
- else
176
- raise RequestFailed, res
177
- end
178
- end
179
-
180
- def payload
181
- @payload
182
- end
183
-
184
- def default_headers
185
- @payload.headers.merge({ :accept => 'application/xml' })
186
- end
187
- end
188
- end
@@ -1,23 +0,0 @@
1
- #
2
- # Replace the request method in Net::HTTP to sniff the body type
3
- # and set the stream if appropriate
4
- #
5
- # Taken from:
6
- # http://www.missiondata.com/blog/ruby/29/streaming-data-to-s3-with-ruby/
7
-
8
- Net::HTTP.ssl_context_accessor(:tmp_dh_callback)
9
-
10
- module Net
11
- class HTTP
12
- alias __request__ request
13
-
14
- def request(req, body=nil, &block)
15
- if body != nil && body.respond_to?(:read)
16
- req.body_stream = body
17
- return __request__(req, nil, &block)
18
- else
19
- return __request__(req, body, &block)
20
- end
21
- end
22
- end
23
- end
@@ -1,185 +0,0 @@
1
- require "tempfile"
2
- require "stringio"
3
-
4
- module RestClient
5
- module Payload
6
- extend self
7
-
8
- def generate(params)
9
- if params.is_a?(String)
10
- Base.new(params)
11
- elsif params.delete(:multipart) == true ||
12
- params.any? { |_,v| v.respond_to?(:path) && v.respond_to?(:read) }
13
- Multipart.new(params)
14
- else
15
- UrlEncoded.new(params)
16
- end
17
- end
18
-
19
- class Base
20
- def initialize(params)
21
- build_stream(params)
22
- end
23
-
24
- def build_stream(params)
25
- @stream = StringIO.new(params)
26
- @stream.seek(0)
27
- end
28
-
29
- def read(bytes=nil)
30
- @stream.read(bytes)
31
- end
32
- alias :to_s :read
33
-
34
- def escape(v)
35
- URI.escape(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
36
- end
37
-
38
- def headers
39
- { 'Content-Length' => size.to_s }
40
- end
41
-
42
- def size
43
- @stream.size
44
- end
45
- alias :length :size
46
-
47
- def close
48
- @stream.close
49
- end
50
- end
51
-
52
- class UrlEncoded < Base
53
- def build_stream(params)
54
- @stream = StringIO.new(params.map do |k,v|
55
- "#{escape(k)}=#{escape(v)}"
56
- end.join("&"))
57
- @stream.seek(0)
58
- end
59
-
60
- def headers
61
- super.merge({ 'Content-Type' => 'application/x-www-form-urlencoded' })
62
- end
63
- end
64
-
65
- class Multipart < Base
66
- EOL = "\r\n"
67
-
68
- def build_stream(params)
69
- b = "--#{boundary}"
70
-
71
- @stream = Tempfile.new("RESTClient.Stream.#{rand(1000)}")
72
- @stream.write(b)
73
- params.each do |k,v|
74
- @stream.write(EOL)
75
- if v.respond_to?(:read) && v.respond_to?(:path)
76
- create_file_field(@stream, k,v)
77
- else
78
- create_regular_field(@stream, k,v)
79
- end
80
- @stream.write(EOL + b)
81
- end
82
- @stream.write('--')
83
- @stream.write(EOL)
84
- @stream.seek(0)
85
- end
86
-
87
- def create_regular_field(s, k, v)
88
- s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"")
89
- s.write(EOL)
90
- s.write(EOL)
91
- s.write(v)
92
- end
93
-
94
- def create_file_field(s, k, v)
95
- begin
96
- s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"; filename=\"#{v.path}\"#{EOL}")
97
- s.write("Content-Type: #{mime_for(v.path)}#{EOL}")
98
- s.write(EOL)
99
- while data = v.read(8124)
100
- s.write(data)
101
- end
102
- ensure
103
- v.close
104
- end
105
- end
106
-
107
- def mime_for(path)
108
- ext = File.extname(path)[1..-1]
109
- MIME_TYPES[ext] || 'text/plain'
110
- end
111
-
112
- def boundary
113
- @boundary ||= rand(1_000_000).to_s
114
- end
115
-
116
- def headers
117
- super.merge({'Content-Type' => %Q{multipart/form-data; boundary="#{boundary}"}})
118
- end
119
-
120
- def close
121
- @stream.close
122
- end
123
- end
124
-
125
- # :stopdoc:
126
- # From WEBrick.
127
- MIME_TYPES = {
128
- "ai" => "application/postscript",
129
- "asc" => "text/plain",
130
- "avi" => "video/x-msvideo",
131
- "bin" => "application/octet-stream",
132
- "bmp" => "image/bmp",
133
- "class" => "application/octet-stream",
134
- "cer" => "application/pkix-cert",
135
- "crl" => "application/pkix-crl",
136
- "crt" => "application/x-x509-ca-cert",
137
- "css" => "text/css",
138
- "dms" => "application/octet-stream",
139
- "doc" => "application/msword",
140
- "dvi" => "application/x-dvi",
141
- "eps" => "application/postscript",
142
- "etx" => "text/x-setext",
143
- "exe" => "application/octet-stream",
144
- "gif" => "image/gif",
145
- "gz" => "application/x-gzip",
146
- "htm" => "text/html",
147
- "html" => "text/html",
148
- "jpe" => "image/jpeg",
149
- "jpeg" => "image/jpeg",
150
- "jpg" => "image/jpeg",
151
- "js" => "text/javascript",
152
- "lha" => "application/octet-stream",
153
- "lzh" => "application/octet-stream",
154
- "mov" => "video/quicktime",
155
- "mpe" => "video/mpeg",
156
- "mpeg" => "video/mpeg",
157
- "mpg" => "video/mpeg",
158
- "pbm" => "image/x-portable-bitmap",
159
- "pdf" => "application/pdf",
160
- "pgm" => "image/x-portable-graymap",
161
- "png" => "image/png",
162
- "pnm" => "image/x-portable-anymap",
163
- "ppm" => "image/x-portable-pixmap",
164
- "ppt" => "application/vnd.ms-powerpoint",
165
- "ps" => "application/postscript",
166
- "qt" => "video/quicktime",
167
- "ras" => "image/x-cmu-raster",
168
- "rb" => "text/plain",
169
- "rd" => "text/plain",
170
- "rtf" => "application/rtf",
171
- "sgm" => "text/sgml",
172
- "sgml" => "text/sgml",
173
- "tif" => "image/tiff",
174
- "tiff" => "image/tiff",
175
- "txt" => "text/plain",
176
- "xbm" => "image/x-xbitmap",
177
- "xls" => "application/vnd.ms-excel",
178
- "xml" => "text/xml",
179
- "xpm" => "image/x-xpixmap",
180
- "xwd" => "image/x-xwindowdump",
181
- "zip" => "application/zip",
182
- }
183
- # :startdoc:
184
- end
185
- end
@@ -1,75 +0,0 @@
1
- module RestClient
2
- # This is the base RestClient exception class. Rescue it if you want to
3
- # catch any exception that your request might raise
4
- class Exception < RuntimeError
5
- def message(default=nil)
6
- self.class::ErrorMessage
7
- end
8
- end
9
-
10
- # A redirect was encountered; caught by execute to retry with the new url.
11
- class Redirect < Exception
12
- ErrorMessage = "Redirect"
13
-
14
- attr_accessor :url
15
- def initialize(url)
16
- @url = url
17
- end
18
- end
19
-
20
- # Authorization is required to access the resource specified.
21
- class Unauthorized < Exception
22
- ErrorMessage = 'Unauthorized'
23
- end
24
-
25
- # No resource was found at the given URL.
26
- class ResourceNotFound < Exception
27
- ErrorMessage = 'Resource not found'
28
- end
29
-
30
- # The server broke the connection prior to the request completing.
31
- class ServerBrokeConnection < Exception
32
- ErrorMessage = 'Server broke connection'
33
- end
34
-
35
- # The server took too long to respond.
36
- class RequestTimeout < Exception
37
- ErrorMessage = 'Request timed out'
38
- end
39
-
40
- # The request failed, meaning the remote HTTP server returned a code other
41
- # than success, unauthorized, or redirect.
42
- #
43
- # The exception message attempts to extract the error from the XML, using
44
- # format returned by Rails: <errors><error>some message</error></errors>
45
- #
46
- # You can get the status code by e.http_code, or see anything about the
47
- # response via e.response. For example, the entire result body (which is
48
- # probably an HTML error page) is e.response.body.
49
- class RequestFailed < Exception
50
- attr_accessor :response
51
-
52
- def initialize(response=nil)
53
- @response = response
54
- end
55
-
56
- def http_code
57
- @response.code.to_i if @response
58
- end
59
-
60
- def message
61
- "HTTP status code #{http_code}"
62
- end
63
-
64
- def to_s
65
- message
66
- end
67
- end
68
- end
69
-
70
- # backwards compatibility
71
- class RestClient::Request
72
- Redirect = RestClient::Redirect
73
- Unauthorized = RestClient::Unauthorized
74
- RequestFailed = RestClient::RequestFailed
75
- end