ftp_service 0.2.0 → 0.3.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.
- 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: []
|