ftp_service 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGELOG.markdown +9 -1
- data/README.markdown +7 -12
- data/Rakefile +7 -2
- data/TODO.markdown +4 -0
- data/VERSION +1 -1
- data/cucumber.yml +1 -0
- data/features/basic_request.feature +19 -0
- data/features/encrypted_request.feature +25 -0
- data/features/step_definitions/ftp_request_steps.rb +68 -0
- data/features/support/env.rb +6 -0
- data/features/support/ftp_helper.rb +13 -0
- data/ftp_service.gemspec +23 -6
- data/lib/ftp_service.rb +76 -9
- data/lib/ftp_service/encryption.rb +17 -0
- data/spec/ftp_service_spec.rb +60 -2
- data/test_keys/pubring.gpg +0 -0
- data/test_keys/secring.gpg +0 -0
- data/test_keys/trustdb.gpg +0 -0
- metadata +51 -10
data/.gitignore
CHANGED
data/CHANGELOG.markdown
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
+
# v0.3.0 (2010-03-18)
|
2
|
+
|
3
|
+
* `FtpService#write_request` and `FtpService#read_response` support
|
4
|
+
encryption/decryption with gpg.
|
5
|
+
* `FtpService#write_request` uses an intermediate temp file while
|
6
|
+
uploading to avoid case where server might try and respond to an
|
7
|
+
in-progress upload of a large request.
|
8
|
+
* `FtpService#read_response` polls for a response.
|
9
|
+
|
1
10
|
# v0.2.0 (2010-03-08)
|
2
11
|
|
3
12
|
* Add `FtpService#write_request` and `FtpService#read_response` methods,
|
4
13
|
making this thing actually usable.
|
5
|
-
|
6
14
|
* Switch to Markdown + Yardoc for rdocs.
|
7
15
|
|
8
16
|
# v0.1.1 (2010-03-08)
|
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
An FTP Service is like a web service except stupid. You send your
|
4
4
|
request by uploading an xml file and get your response by downloading
|
5
5
|
another xml file. Have you ever had to deal with something like that? I
|
6
|
-
have.
|
6
|
+
have. It sucks.
|
7
7
|
|
8
8
|
RDocs on [rdoc.info](http://rdoc.info/projects/blaix/ftp_service).
|
9
9
|
|
@@ -18,20 +18,15 @@ Source code on [github](http://github.com/blaix/ftp_service).
|
|
18
18
|
require 'ftp_service'
|
19
19
|
|
20
20
|
FtpService.open('host', 'user', 'pass') do |service|
|
21
|
-
|
22
|
-
service.
|
23
|
-
response = service.read_response("#{path}/response.xml")
|
21
|
+
service.write_request('<foo>bar</foo>', "/request/path.xml")
|
22
|
+
response = service.read_response("/response/path.xml")
|
24
23
|
end
|
25
24
|
|
26
|
-
* `read_response` will block while it polls the server waiting for a
|
27
|
-
response.
|
28
|
-
* Temp files are created for the local request and response files and
|
29
|
-
deleted when no longer needed.
|
30
|
-
|
31
25
|
For more details, see the
|
32
|
-
[RDocs](http://rdoc.info/projects/blaix/ftp_service)
|
33
|
-
really yardocs!).
|
26
|
+
[RDocs](http://rdoc.info/projects/blaix/ftp_service).
|
34
27
|
|
35
28
|
## Copyright
|
36
29
|
|
37
|
-
Copyright (c) 2010 Justin Blake. See
|
30
|
+
Copyright (c) 2010 Justin Blake. See
|
31
|
+
[LICENSE](http://github.com/blaix/ftp_service/raw/master/LICENSE) for
|
32
|
+
details.
|
data/Rakefile
CHANGED
@@ -10,9 +10,11 @@ begin
|
|
10
10
|
gem.email = "justin@megablaix.com"
|
11
11
|
gem.homepage = "http://github.com/blaix/ftp_service"
|
12
12
|
gem.authors = ["Justin Blake"]
|
13
|
+
gem.add_dependency "ruby_gpg", ">= 0.2.0"
|
13
14
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
15
|
gem.add_development_dependency "mocha", ">= 0.9.8"
|
15
|
-
gem.add_development_dependency "yard", ">= 0"
|
16
|
+
gem.add_development_dependency "yard", ">= 0.5.3"
|
17
|
+
gem.add_development_dependency "cucumber", ">= 0.6.3"
|
16
18
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
19
|
end
|
18
20
|
Jeweler::GemcutterTasks.new
|
@@ -26,6 +28,9 @@ Spec::Rake::SpecTask.new(:spec) do |spec|
|
|
26
28
|
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
29
|
end
|
28
30
|
|
31
|
+
require 'cucumber/rake/task'
|
32
|
+
Cucumber::Rake::Task.new(:features)
|
33
|
+
|
29
34
|
namespace :spec do
|
30
35
|
Spec::Rake::SpecTask.new(:doc) do |spec|
|
31
36
|
spec.libs << 'lib' << 'spec'
|
@@ -47,7 +52,7 @@ task :default => :spec
|
|
47
52
|
begin
|
48
53
|
require 'yard'
|
49
54
|
YARD::Rake::YardocTask.new do |y|
|
50
|
-
y.files << '-' << 'CHANGELOG.*'
|
55
|
+
y.files << '-' << 'CHANGELOG.*' << 'TODO.*'
|
51
56
|
end
|
52
57
|
rescue LoadError
|
53
58
|
task :yardoc do
|
data/TODO.markdown
ADDED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: features
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# To run, you must have an FTP server running and accessible by the
|
2
|
+
# credentials defined in features/support/ftp_helper.rb
|
3
|
+
|
4
|
+
Feature: Making a request
|
5
|
+
In order to take advantage of a web service over FTP
|
6
|
+
As a poor unfortunate soul
|
7
|
+
I want to make a request
|
8
|
+
|
9
|
+
Background:
|
10
|
+
Given I connect to an FTP service
|
11
|
+
|
12
|
+
Scenario: send a request
|
13
|
+
When I send the request "request" to the path "request_path"
|
14
|
+
Then the request "request" should exist at "request_path"
|
15
|
+
|
16
|
+
Scenario: read a response
|
17
|
+
When the server responds with "response" at the path "response_path"
|
18
|
+
Then I can read the response at the path "response_path"
|
19
|
+
And the response should be "response"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# To run, you must have an FTP server running and accessible by the
|
2
|
+
# credentials defined in features/support/ftp_helper.rb
|
3
|
+
|
4
|
+
# The encryption uses the gpg keys in the test_keys dir.
|
5
|
+
|
6
|
+
Feature: GPG Encryption
|
7
|
+
In order to keep my request secure over insecure FTP
|
8
|
+
As a user
|
9
|
+
I want to use gpg to encrypt and decrypt my request and response files
|
10
|
+
|
11
|
+
Background:
|
12
|
+
Given I connect to an FTP service
|
13
|
+
|
14
|
+
Scenario: send a request
|
15
|
+
When I send the request "secret content" to the path "request_path.gpg" with gpg recipient "Slow Joe Crow"
|
16
|
+
Then a binary request should exist at "request_path.gpg"
|
17
|
+
And the binary request at "request_path.gpg" should not contain "secret content"
|
18
|
+
When I download the binary request at "request_path.gpg" to "downloaded_request.gpg"
|
19
|
+
And I decrypt the file "downloaded_request.gpg" with passphrase "test"
|
20
|
+
Then the file "downloaded_request" should contain "secret content"
|
21
|
+
|
22
|
+
Scenario: read a response
|
23
|
+
When the server responds with "secret response" encrypted for "Slow Joe Crow" at the path "response_path.gpg"
|
24
|
+
Then I can read the response at the path "response_path.gpg" with the passphrase "test"
|
25
|
+
And the response should be "secret response"
|
@@ -0,0 +1,68 @@
|
|
1
|
+
Given /^I connect to an FTP service$/ do
|
2
|
+
@service = FtpService.new(FtpHelper::SERVER, FtpHelper::USER, FtpHelper::PASS)
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I send the request "([^\"]*)" to the path "([^\"]*)"$/ do |request, remote_path|
|
6
|
+
@service.write_request(request, remote_path)
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I send the request "([^\"]*)" to the path "([^\"]*)" with gpg recipient "([^\"]*)"$/ do |request, remote_path, gpg_recipient|
|
10
|
+
@service.write_request(request, remote_path, :gpg_recipient => gpg_recipient)
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^the server responds with "([^\"]*)" at the path "([^\"]*)"$/ do |response, remote_path|
|
14
|
+
response = StringIO.new(response)
|
15
|
+
ftp.storlines("STOR #{remote_path}", response)
|
16
|
+
end
|
17
|
+
|
18
|
+
When /^the server responds with "([^\"]*)" encrypted for "([^\"]*)" at the path "([^\"]*)"$/ do |response, gpg_recipient, remote_path|
|
19
|
+
# Cheating a bit here to mimic a ftp service response by sending a request...
|
20
|
+
@service.write_request(response, remote_path, :gpg_recipient => gpg_recipient)
|
21
|
+
end
|
22
|
+
|
23
|
+
When /^I download the binary request at "([^\"]*)" to "([^\"]*)"$/ do |remote_path, local_path|
|
24
|
+
File.delete(local_path) if File.exist?(local_path)
|
25
|
+
ftp.getbinaryfile(remote_path, "#{TMP_PATH}/#{local_path}")
|
26
|
+
end
|
27
|
+
|
28
|
+
When /^I decrypt the file "([^\"]*)" with passphrase "([^\"]*)"$/ do |filename, passphrase|
|
29
|
+
RubyGpg.decrypt("#{TMP_PATH}/#{filename}", passphrase)
|
30
|
+
end
|
31
|
+
|
32
|
+
Then /^the request "([^\"]*)" should exist at "([^\"]*)"$/ do |request, remote_path|
|
33
|
+
actual_request = ""
|
34
|
+
ftp.retrlines("RETR #{remote_path}") { |line| actual_request << line }
|
35
|
+
actual_request.should == request
|
36
|
+
end
|
37
|
+
|
38
|
+
Then /^a binary request should exist at "([^\"]*)"$/ do |remote_path|
|
39
|
+
lambda {
|
40
|
+
ftp.retrbinary("RETR #{remote_path}", 128) {}
|
41
|
+
}.should_not raise_error
|
42
|
+
end
|
43
|
+
|
44
|
+
Then /^the binary request at "([^\"]*)" should not contain "([^\"]*)"$/ do |remote_path, request|
|
45
|
+
actual = ""
|
46
|
+
ftp.retrbinary("RETR #{remote_path}", 128) { |chunk| actual << chunk }
|
47
|
+
actual.strip.should_not == request.strip
|
48
|
+
end
|
49
|
+
|
50
|
+
Then /^I can read the response at the path "([^\"]*)"$/ do |remote_path|
|
51
|
+
@actual_response = @service.read_response(remote_path)
|
52
|
+
end
|
53
|
+
|
54
|
+
Then /^I can read the response at the path "([^\"]*)" with the passphrase "([^\"]*)"$/ do |remote_path, gpg_passphrase|
|
55
|
+
@actual_response = @service.read_response(remote_path, :gpg_passphrase => gpg_passphrase)
|
56
|
+
end
|
57
|
+
|
58
|
+
Then /^the response should be "([^\"]*)"$/ do |response|
|
59
|
+
@actual_response.strip.should == response
|
60
|
+
end
|
61
|
+
|
62
|
+
Then /^the file "([^\"]*)" should contain "([^\"]*)"$/ do |filename, contents|
|
63
|
+
File.read("#{TMP_PATH}/#{filename}").strip.should == contents.strip
|
64
|
+
end
|
65
|
+
|
66
|
+
After do
|
67
|
+
@service.close if @service
|
68
|
+
end
|
data/ftp_service.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ftp_service}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Justin Blake"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-18}
|
13
13
|
s.description = %q{An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.}
|
14
14
|
s.email = %q{justin@megablaix.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -22,14 +22,25 @@ Gem::Specification.new do |s|
|
|
22
22
|
"LICENSE",
|
23
23
|
"README.markdown",
|
24
24
|
"Rakefile",
|
25
|
+
"TODO.markdown",
|
25
26
|
"VERSION",
|
27
|
+
"cucumber.yml",
|
28
|
+
"features/basic_request.feature",
|
29
|
+
"features/encrypted_request.feature",
|
30
|
+
"features/step_definitions/ftp_request_steps.rb",
|
31
|
+
"features/support/env.rb",
|
32
|
+
"features/support/ftp_helper.rb",
|
26
33
|
"ftp_service.gemspec",
|
27
34
|
"lib/ftp_service.rb",
|
35
|
+
"lib/ftp_service/encryption.rb",
|
28
36
|
"lib/tempfile_helper.rb",
|
29
37
|
"spec/ftp_service_spec.rb",
|
30
38
|
"spec/spec.opts",
|
31
39
|
"spec/spec_helper.rb",
|
32
|
-
"spec/tempfile_helper_spec.rb"
|
40
|
+
"spec/tempfile_helper_spec.rb",
|
41
|
+
"test_keys/pubring.gpg",
|
42
|
+
"test_keys/secring.gpg",
|
43
|
+
"test_keys/trustdb.gpg"
|
33
44
|
]
|
34
45
|
s.homepage = %q{http://github.com/blaix/ftp_service}
|
35
46
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -47,18 +58,24 @@ Gem::Specification.new do |s|
|
|
47
58
|
s.specification_version = 3
|
48
59
|
|
49
60
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
61
|
+
s.add_runtime_dependency(%q<ruby_gpg>, [">= 0.2.0"])
|
50
62
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
51
63
|
s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
|
52
|
-
s.add_development_dependency(%q<yard>, [">= 0"])
|
64
|
+
s.add_development_dependency(%q<yard>, [">= 0.5.3"])
|
65
|
+
s.add_development_dependency(%q<cucumber>, [">= 0.6.3"])
|
53
66
|
else
|
67
|
+
s.add_dependency(%q<ruby_gpg>, [">= 0.2.0"])
|
54
68
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
55
69
|
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
56
|
-
s.add_dependency(%q<yard>, [">= 0"])
|
70
|
+
s.add_dependency(%q<yard>, [">= 0.5.3"])
|
71
|
+
s.add_dependency(%q<cucumber>, [">= 0.6.3"])
|
57
72
|
end
|
58
73
|
else
|
74
|
+
s.add_dependency(%q<ruby_gpg>, [">= 0.2.0"])
|
59
75
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
60
76
|
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
61
|
-
s.add_dependency(%q<yard>, [">= 0"])
|
77
|
+
s.add_dependency(%q<yard>, [">= 0.5.3"])
|
78
|
+
s.add_dependency(%q<cucumber>, [">= 0.6.3"])
|
62
79
|
end
|
63
80
|
end
|
64
81
|
|
data/lib/ftp_service.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'net/ftp'
|
2
2
|
require 'tempfile_helper'
|
3
|
+
require 'ftp_service/encryption'
|
3
4
|
|
4
5
|
# Class for dealing with a service that acts like a web service, except
|
5
6
|
# over FTP. Meaning an xml request is uploaded as a file, and the
|
@@ -21,6 +22,7 @@ require 'tempfile_helper'
|
|
21
22
|
# response = service.read_response("#{path}/response.xml")
|
22
23
|
# service.close
|
23
24
|
class FtpService
|
25
|
+
include Encryption
|
24
26
|
|
25
27
|
# Open a connection to the FTP server and return an FtpService object.
|
26
28
|
# The object must be closed explicitely. See FtpServier#open for a
|
@@ -42,18 +44,49 @@ class FtpService
|
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
45
|
-
# Write
|
47
|
+
# Write +request+ to a local temp file and upload it to +remote_path+
|
46
48
|
# on the FTP server.
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
#
|
50
|
+
# ftp_service.write_request('<foo>bar</foo>', '/remote/path.xml')
|
51
|
+
#
|
52
|
+
# You can encrypt the request using GPG:
|
53
|
+
#
|
54
|
+
# ftp_service.write_request('<secret>stuff</secret>', '/remote/path.xml.gpg', :gpg_recipient => 'recipient@email.com')
|
55
|
+
#
|
56
|
+
# You must have +gpg+ installed and have a public key available for
|
57
|
+
# the intended recipient. This uses the +ruby_gpg+ gem. To configure
|
58
|
+
# the gpg settings, see {http://rdoc.info/projects/blaix/ruby_gpg}.
|
59
|
+
def write_request(request, remote_path, options = {})
|
60
|
+
request = TempfileHelper.write(request, 'request')
|
61
|
+
remote_temp_path = remote_path + ".tmp"
|
62
|
+
if options[:gpg_recipient]
|
63
|
+
encrypt(request, options[:gpg_recipient])
|
64
|
+
@ftp.putbinaryfile(request.path, remote_temp_path)
|
65
|
+
else
|
66
|
+
@ftp.puttextfile(request.path, remote_temp_path)
|
67
|
+
end
|
68
|
+
@ftp.rename(remote_temp_path, remote_path)
|
50
69
|
end
|
51
70
|
|
52
|
-
# Download the file at
|
53
|
-
# temp file and return its contents.
|
54
|
-
|
55
|
-
|
56
|
-
|
71
|
+
# Download the file at +remote_path+ from the FTP server to a local
|
72
|
+
# temp file and return its contents. If +remote_path+ doesn't exist,
|
73
|
+
# keep trying for 2 minutes before raising a Timeout::Error.
|
74
|
+
#
|
75
|
+
# response = ftp_service.read_response('/remote/path.xml')
|
76
|
+
#
|
77
|
+
# If you expect the response to be encrypted for you with gpg:
|
78
|
+
#
|
79
|
+
# response = ftp_service.read_response('/remote/path.xml.gpg', :gpg_passphrase => "my_passphrase")
|
80
|
+
#
|
81
|
+
# You must have +gpg+ installed and have the necessarry private key.
|
82
|
+
# This uses the +ruby_gpg+ gem. To configure the gpg settings, see
|
83
|
+
# {http://rdoc.info/projects/blaix/ruby_gpg}.
|
84
|
+
def read_response(remote_path, options = {})
|
85
|
+
response = download_and_read_response(remote_path, options)
|
86
|
+
if options[:gpg_passphrase]
|
87
|
+
RubyGpg.decrypt_string(response, options[:gpg_passphrase])
|
88
|
+
else
|
89
|
+
response
|
57
90
|
end
|
58
91
|
end
|
59
92
|
|
@@ -61,4 +94,38 @@ class FtpService
|
|
61
94
|
def close
|
62
95
|
@ftp.close
|
63
96
|
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def download_and_read_response(remote_path, options = {})
|
101
|
+
TempfileHelper.read('response') do |tmp|
|
102
|
+
Timeout::timeout(120) do
|
103
|
+
loop_until_downloaded(remote_path, tmp.path, options)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def loop_until_downloaded(remote_path, local_path, options = {})
|
109
|
+
loop do
|
110
|
+
begin
|
111
|
+
download(remote_path, local_path, options)
|
112
|
+
break
|
113
|
+
rescue Net::FTPPermError => e
|
114
|
+
raise unless e.message.include?("No such file")
|
115
|
+
rest_between_requests
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def download(remote_path, local_path, options = {})
|
121
|
+
if options[:gpg_passphrase]
|
122
|
+
@ftp.getbinaryfile(remote_path, local_path)
|
123
|
+
else
|
124
|
+
@ftp.gettextfile(remote_path, local_path)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def rest_between_requests
|
129
|
+
sleep(2)
|
130
|
+
end
|
64
131
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'ruby_gpg'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
require 'ruby_gpg'
|
6
|
+
end
|
7
|
+
|
8
|
+
class FtpService
|
9
|
+
module Encryption
|
10
|
+
private
|
11
|
+
# Expects a tempfile object and a string for the recipient.
|
12
|
+
def encrypt(file, recipient)
|
13
|
+
RubyGpg.encrypt(file.path, recipient)
|
14
|
+
file.path << ".gpg"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/ftp_service_spec.rb
CHANGED
@@ -54,9 +54,28 @@ describe "FtpService" do
|
|
54
54
|
@service.write_request('request', '/remote/path')
|
55
55
|
end
|
56
56
|
|
57
|
-
it "
|
57
|
+
it "encrypts the request if passed a gpg recipient" do
|
58
58
|
TempfileHelper.stubs(:write).returns(@tempfile)
|
59
|
-
|
59
|
+
RubyGpg.expects(:encrypt).with('/local/path', 'recipient')
|
60
|
+
@service.write_request('request', '/remote/path.gpg', :gpg_recipient => 'recipient')
|
61
|
+
end
|
62
|
+
|
63
|
+
it "uploads the request to a temp path on the FTP server" do
|
64
|
+
TempfileHelper.stubs(:write).returns(@tempfile)
|
65
|
+
@ftp.expects(:puttextfile).with('/local/path', '/remote/path.tmp')
|
66
|
+
@service.write_request('request', '/remote/path')
|
67
|
+
end
|
68
|
+
|
69
|
+
it "uploads the request as binary if passed a gpg recipient" do
|
70
|
+
TempfileHelper.stubs(:write).returns(@tempfile)
|
71
|
+
RubyGpg.stubs(:encrypt)
|
72
|
+
@ftp.expects(:putbinaryfile).with('/local/path.gpg', '/remote/path.gpg.tmp')
|
73
|
+
@service.write_request('request', '/remote/path.gpg', :gpg_recipient => 'recipient')
|
74
|
+
end
|
75
|
+
|
76
|
+
it "renames the temp path on the FTP server to the passed `path`" do
|
77
|
+
TempfileHelper.stubs(:write).returns(@tempfile)
|
78
|
+
@ftp.expects(:rename).with('/remote/path.tmp', '/remote/path')
|
60
79
|
@service.write_request('request', '/remote/path')
|
61
80
|
end
|
62
81
|
end
|
@@ -65,7 +84,10 @@ describe "FtpService" do
|
|
65
84
|
before do
|
66
85
|
tempfile = stub('tempfile', :path => '/local/path')
|
67
86
|
TempfileHelper.stubs(:read).returns('response').yields(tempfile)
|
87
|
+
|
68
88
|
@service = FtpService.new('host', 'user', 'pass')
|
89
|
+
# No need to be nice to the "server" during testing...
|
90
|
+
@service.stubs(:rest_between_requests)
|
69
91
|
end
|
70
92
|
|
71
93
|
it "downloads the response at `path` from the FTP server" do
|
@@ -73,9 +95,45 @@ describe "FtpService" do
|
|
73
95
|
@service.read_response('/remote/path')
|
74
96
|
end
|
75
97
|
|
98
|
+
it "downloads the response as binary if passed a gpg passphrase" do
|
99
|
+
RubyGpg.stubs(:decrypt_string)
|
100
|
+
@ftp.expects(:getbinaryfile).with('/remote/path.gpg', '/local/path')
|
101
|
+
@service.read_response('/remote/path.gpg', :gpg_passphrase => "my_passphrase")
|
102
|
+
end
|
103
|
+
|
104
|
+
it "decrypts the response if passed a gpg passphrase" do
|
105
|
+
RubyGpg.expects(:decrypt_string).with('response', 'my_passphrase')
|
106
|
+
@service.read_response('/remote/path.gpg', :gpg_passphrase => "my_passphrase")
|
107
|
+
end
|
108
|
+
|
76
109
|
it "returns the contents of the downloaded response" do
|
77
110
|
@service.read_response('/remote/path').should == "response"
|
78
111
|
end
|
112
|
+
|
113
|
+
it "polls until response shows up" do
|
114
|
+
error = Net::FTPPermError.new("No such file")
|
115
|
+
# Raise error on the first two calls...
|
116
|
+
@ftp.expects(:gettextfile).times(3).raises(error).then.raises(error).then.returns(nil)
|
117
|
+
lambda {
|
118
|
+
@service.read_response('/remote/path')
|
119
|
+
}.should_not raise_error
|
120
|
+
end
|
121
|
+
|
122
|
+
it "times out if response takes longer than 2 minutes to show up" do
|
123
|
+
# TODO: Less brittle way to test this?
|
124
|
+
# Currently depends on inner workings of Timeout.
|
125
|
+
Timeout.expects(:sleep).with(120)
|
126
|
+
lambda {
|
127
|
+
@service.read_response('/remote/path')
|
128
|
+
}.should raise_error(Timeout::Error)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "doesn't gobble up every FTP exception" do
|
132
|
+
@ftp.stubs(:gettextfile).raises(Net::FTPPermError.new("Permission denied")).then.returns(nil)
|
133
|
+
lambda {
|
134
|
+
@service.read_response('/remote/path')
|
135
|
+
}.should raise_error(Net::FTPPermError, "Permission denied")
|
136
|
+
end
|
79
137
|
end
|
80
138
|
|
81
139
|
describe '#close' do
|
Binary file
|
Binary file
|
Binary file
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Justin Blake
|
@@ -14,13 +14,27 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-18 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: ruby_gpg
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 2
|
30
|
+
- 0
|
31
|
+
version: 0.2.0
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
24
38
|
requirements:
|
25
39
|
- - ">="
|
26
40
|
- !ruby/object:Gem::Version
|
@@ -30,11 +44,11 @@ dependencies:
|
|
30
44
|
- 9
|
31
45
|
version: 1.2.9
|
32
46
|
type: :development
|
33
|
-
version_requirements: *
|
47
|
+
version_requirements: *id002
|
34
48
|
- !ruby/object:Gem::Dependency
|
35
49
|
name: mocha
|
36
50
|
prerelease: false
|
37
|
-
requirement: &
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
38
52
|
requirements:
|
39
53
|
- - ">="
|
40
54
|
- !ruby/object:Gem::Version
|
@@ -44,19 +58,35 @@ dependencies:
|
|
44
58
|
- 8
|
45
59
|
version: 0.9.8
|
46
60
|
type: :development
|
47
|
-
version_requirements: *
|
61
|
+
version_requirements: *id003
|
48
62
|
- !ruby/object:Gem::Dependency
|
49
63
|
name: yard
|
50
64
|
prerelease: false
|
51
|
-
requirement: &
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
66
|
requirements:
|
53
67
|
- - ">="
|
54
68
|
- !ruby/object:Gem::Version
|
55
69
|
segments:
|
56
70
|
- 0
|
57
|
-
|
71
|
+
- 5
|
72
|
+
- 3
|
73
|
+
version: 0.5.3
|
58
74
|
type: :development
|
59
|
-
version_requirements: *
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: cucumber
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
- 6
|
86
|
+
- 3
|
87
|
+
version: 0.6.3
|
88
|
+
type: :development
|
89
|
+
version_requirements: *id005
|
60
90
|
description: An FTP Service is like a web service except stupid. You send your request by uploading an xml file and get your response by downloading another xml file.
|
61
91
|
email: justin@megablaix.com
|
62
92
|
executables: []
|
@@ -72,14 +102,25 @@ files:
|
|
72
102
|
- LICENSE
|
73
103
|
- README.markdown
|
74
104
|
- Rakefile
|
105
|
+
- TODO.markdown
|
75
106
|
- VERSION
|
107
|
+
- cucumber.yml
|
108
|
+
- features/basic_request.feature
|
109
|
+
- features/encrypted_request.feature
|
110
|
+
- features/step_definitions/ftp_request_steps.rb
|
111
|
+
- features/support/env.rb
|
112
|
+
- features/support/ftp_helper.rb
|
76
113
|
- ftp_service.gemspec
|
77
114
|
- lib/ftp_service.rb
|
115
|
+
- lib/ftp_service/encryption.rb
|
78
116
|
- lib/tempfile_helper.rb
|
79
117
|
- spec/ftp_service_spec.rb
|
80
118
|
- spec/spec.opts
|
81
119
|
- spec/spec_helper.rb
|
82
120
|
- spec/tempfile_helper_spec.rb
|
121
|
+
- test_keys/pubring.gpg
|
122
|
+
- test_keys/secring.gpg
|
123
|
+
- test_keys/trustdb.gpg
|
83
124
|
has_rdoc: true
|
84
125
|
homepage: http://github.com/blaix/ftp_service
|
85
126
|
licenses: []
|