httpthumbnailer-client 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -7
- data/Gemfile.lock +56 -49
- data/README.md +39 -15
- data/VERSION +1 -1
- data/bin/httpthumbnailer-client +73 -0
- data/httpthumbnailer-client.gemspec +38 -26
- data/lib/httpthumbnailer-client.rb +122 -48
- data/spec/httpthumbnailer-client_spec.rb +9 -138
- data/spec/spec_helper.rb +11 -4
- data/spec/{test-large.jpg → support/test-large.jpg} +0 -0
- data/spec/{test.jpg → support/test.jpg} +0 -0
- data/spec/{test.txt → support/test.txt} +0 -0
- data/spec/thumbnail_spec.rb +66 -0
- data/spec/thumbnails_spec.rb +110 -0
- data/spec/uri_builder_spec.rb +16 -0
- metadata +83 -32
- data/lib/httpthumbnailer-client/multipart_response.rb +0 -45
- data/spec/multipart_response_spec.rb +0 -95
@@ -1,45 +0,0 @@
|
|
1
|
-
class MultipartResponse
|
2
|
-
class NoBoundaryFoundInContentTypeError < ArgumentError
|
3
|
-
def initialize(content_type_header, exception)
|
4
|
-
super("Content-Type header of '#{content_type_header}' has no boundary defined: #{exception.class.name}: #{exception}")
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
class Part
|
9
|
-
def initialize(data)
|
10
|
-
if data.include?("\r\n\r\n")
|
11
|
-
headers, *body = *data.split("\r\n\r\n")
|
12
|
-
@headers = Hash[headers.split("\r\n").map{|h| h.split(/: ?/)}]
|
13
|
-
@body = body.join("\r\n\r\n")
|
14
|
-
else
|
15
|
-
@headers = {'Content-Type' => 'text/plain'}
|
16
|
-
@body = data
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
attr_reader :headers, :body
|
21
|
-
alias :header :headers
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize(content_type_header, body)
|
25
|
-
@boundary = begin
|
26
|
-
content_type_header.split(';').map{|e| e.strip}.select{|e| e =~ /^boundary=/}.first.match(/^boundary="(.*)"/)[1]
|
27
|
-
rescue => e
|
28
|
-
raise NoBoundaryFoundInContentTypeError.new(content_type_header, e)
|
29
|
-
end
|
30
|
-
|
31
|
-
body, epilogue = *body.split("--#{@boundary}--")
|
32
|
-
preamble, *parts = *body.split("--#{@boundary}")
|
33
|
-
|
34
|
-
@preamble = preamble.sub(/\r\n$/m, '')
|
35
|
-
@preamble = nil if @preamble.empty?
|
36
|
-
|
37
|
-
@epilogue = epilogue.sub(/^\r\n/m, '') if epilogue
|
38
|
-
|
39
|
-
@parts = parts.map{|p| p.sub(/^\r\n/m, '').sub(/\r\n$/m, '')}.map{|p| Part.new(p)}
|
40
|
-
end
|
41
|
-
|
42
|
-
attr_reader :boundary, :preamble, :parts, :epilogue
|
43
|
-
alias :part :parts
|
44
|
-
end
|
45
|
-
|
@@ -1,95 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
require 'httpthumbnailer-client/multipart_response'
|
3
|
-
|
4
|
-
describe MultipartResponse do
|
5
|
-
describe "parsing" do
|
6
|
-
it "should privide preamble, parts with headers and epilogue" do
|
7
|
-
content_type_header = 'multipart/mixed; boundary="cut here"'
|
8
|
-
body =
|
9
|
-
"""hello
|
10
|
-
--cut here
|
11
|
-
Content-Type: text/plain
|
12
|
-
|
13
|
-
part 1
|
14
|
-
--cut here
|
15
|
-
Content-Type: text/html
|
16
|
-
Content-Transfer-Encoding: base64
|
17
|
-
|
18
|
-
part 2
|
19
|
-
--cut here
|
20
|
-
part 3
|
21
|
-
--cut here--
|
22
|
-
world""".gsub!("\n", "\r\n")
|
23
|
-
|
24
|
-
mr = MultipartResponse.new(content_type_header, body)
|
25
|
-
mr.preamble.should == "hello"
|
26
|
-
|
27
|
-
mr.parts[0].body.should == "part 1"
|
28
|
-
mr.parts[0].header['Content-Type'].should == "text/plain"
|
29
|
-
|
30
|
-
mr.parts[1].body.should == "part 2"
|
31
|
-
mr.parts[1].header['Content-Type'].should == "text/html"
|
32
|
-
mr.parts[1].header['Content-Transfer-Encoding'].should == "base64"
|
33
|
-
|
34
|
-
mr.parts[2].body.should == "part 3"
|
35
|
-
|
36
|
-
mr.epilogue.should == "world"
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should privide nil preamble if no prologue sent" do
|
40
|
-
content_type_header = 'multipart/mixed; boundary="cut here"'
|
41
|
-
body =
|
42
|
-
"""--cut here
|
43
|
-
part 1
|
44
|
-
--cut here--""".gsub!("\n", "\r\n")
|
45
|
-
|
46
|
-
mr = MultipartResponse.new(content_type_header, body)
|
47
|
-
mr.preamble.should be_nil
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should privide nil epilogue if no epilogue sent" do
|
51
|
-
content_type_header = 'multipart/mixed; boundary="cut here"'
|
52
|
-
body =
|
53
|
-
"""--cut here
|
54
|
-
part 1
|
55
|
-
--cut here--""".gsub!("\n", "\r\n")
|
56
|
-
|
57
|
-
mr = MultipartResponse.new(content_type_header, body)
|
58
|
-
mr.epilogue.should be_nil
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should provide default mime type of text/plain if no Content-Type header specified" do
|
62
|
-
content_type_header = 'multipart/mixed; boundary="cut here"'
|
63
|
-
body =
|
64
|
-
"""--cut here
|
65
|
-
part 1
|
66
|
-
--cut here--""".gsub!("\n", "\r\n")
|
67
|
-
|
68
|
-
mr = MultipartResponse.new(content_type_header, body)
|
69
|
-
mr.part[0].header['Content-Type'].should == 'text/plain'
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should fail with MultipartResponse::NoBoundaryFoundInContentTypeError if no boundary specified in content type header" do
|
73
|
-
lambda {
|
74
|
-
MultipartResponse.new("fas", "")
|
75
|
-
}.should raise_error MultipartResponse::NoBoundaryFoundInContentTypeError
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
it "provides part alias" do
|
80
|
-
content_type_header = 'multipart/mixed; boundary="cut here"'
|
81
|
-
body =
|
82
|
-
"""--cut here
|
83
|
-
part 1
|
84
|
-
--cut here
|
85
|
-
part 2
|
86
|
-
--cut here
|
87
|
-
part 3
|
88
|
-
--cut here--""".gsub!("\n", "\r\n")
|
89
|
-
|
90
|
-
mr = MultipartResponse.new(content_type_header, body)
|
91
|
-
mr.part[0].body.should == "part 1"
|
92
|
-
mr.part[1].body.should == "part 2"
|
93
|
-
mr.part[2].body.should == "part 3"
|
94
|
-
end
|
95
|
-
end
|