httpimagestore 1.4.1 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.idea/.name +1 -0
- data/.idea/.rakeTasks +7 -0
- data/.idea/codeStyleSettings.xml +13 -0
- data/.idea/dictionaries/wcc.xml +8 -0
- data/.idea/encodings.xml +5 -0
- data/.idea/httpimagestore.iml +69 -0
- data/.idea/jenkinsSettings.xml +9 -0
- data/.idea/misc.xml +5 -0
- data/.idea/modules.xml +9 -0
- data/.idea/scopes/scope_settings.xml +5 -0
- data/.idea/vcs.xml +7 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +4 -4
- data/README.md +55 -33
- data/VERSION +1 -1
- data/bin/httpimagestore +19 -5
- data/features/cache-control.feature +8 -9
- data/features/compatibility.feature +46 -21
- data/features/error-reporting.feature +15 -16
- data/features/flexi.feature +4 -5
- data/features/health-check.feature +1 -2
- data/features/request-matching.feature +211 -0
- data/features/s3-store-and-thumbnail.feature +3 -10
- data/features/storage.feature +7 -9
- data/httpimagestore.gemspec +17 -5
- data/lib/httpimagestore/configuration/handler.rb +55 -30
- data/lib/httpimagestore/configuration/output.rb +51 -2
- data/spec/configuration_handler_spec.rb +4 -22
- data/spec/configuration_output_spec.rb +86 -2
- metadata +17 -5
data/features/storage.feature
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
Feature: Storing images under different names
|
2
2
|
Storage supports UUID and SHA digest based auto generated storage as well as user provided via request or static configuration string.
|
3
3
|
|
4
|
-
|
5
4
|
Background:
|
6
5
|
Given httpthumbnailer server is running at http://localhost:3100/health_check
|
7
6
|
Given httpimagestore server is running at http://localhost:3000/health_check with the following configuration
|
8
7
|
"""
|
9
|
-
path "input_digest"
|
10
|
-
path "input_sha256"
|
11
|
-
path "image_digest"
|
12
|
-
path "image_sha256"
|
13
|
-
path "uuid"
|
14
|
-
path "image_meta"
|
15
|
-
path "input_image_meta"
|
8
|
+
path "input_digest" "#{input_digest}"
|
9
|
+
path "input_sha256" "#{input_sha256}"
|
10
|
+
path "image_digest" "#{image_digest}"
|
11
|
+
path "image_sha256" "#{image_sha256}"
|
12
|
+
path "uuid" "#{uuid}"
|
13
|
+
path "image_meta" "#{image_width}x#{image_height}.#{image_mime_extension}"
|
14
|
+
path "input_image_meta" "#{input_image_width}x#{input_image_height}.#{input_image_mime_extension}"
|
16
15
|
|
17
16
|
post "images" "input_digest" {
|
18
17
|
thumbnail "input" "thumbnail" operation="crop" width="50" height="50"
|
@@ -196,4 +195,3 @@ Feature: Storing images under different names
|
|
196
195
|
509x719.png
|
197
196
|
"""
|
198
197
|
Then file /tmp/509x719.png will contain PNG image of size 50x100
|
199
|
-
|
data/httpimagestore.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "httpimagestore"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jakub Pastuszek"]
|
12
|
-
s.date = "2013-10-
|
12
|
+
s.date = "2013-10-22"
|
13
13
|
s.description = "Thumbnails images using httpthumbnailer and stored data on HTTP server (S3)"
|
14
14
|
s.email = "jpastuszek@gmail.com"
|
15
15
|
s.executables = ["httpimagestore"]
|
@@ -19,6 +19,17 @@ Gem::Specification.new do |s|
|
|
19
19
|
]
|
20
20
|
s.files = [
|
21
21
|
".document",
|
22
|
+
".idea/.name",
|
23
|
+
".idea/.rakeTasks",
|
24
|
+
".idea/codeStyleSettings.xml",
|
25
|
+
".idea/dictionaries/wcc.xml",
|
26
|
+
".idea/encodings.xml",
|
27
|
+
".idea/httpimagestore.iml",
|
28
|
+
".idea/jenkinsSettings.xml",
|
29
|
+
".idea/misc.xml",
|
30
|
+
".idea/modules.xml",
|
31
|
+
".idea/scopes/scope_settings.xml",
|
32
|
+
".idea/vcs.xml",
|
22
33
|
".rspec",
|
23
34
|
"Gemfile",
|
24
35
|
"Gemfile.lock",
|
@@ -32,6 +43,7 @@ Gem::Specification.new do |s|
|
|
32
43
|
"features/error-reporting.feature",
|
33
44
|
"features/flexi.feature",
|
34
45
|
"features/health-check.feature",
|
46
|
+
"features/request-matching.feature",
|
35
47
|
"features/s3-store-and-thumbnail.feature",
|
36
48
|
"features/step_definitions/httpimagestore_steps.rb",
|
37
49
|
"features/storage.feature",
|
@@ -81,7 +93,7 @@ Gem::Specification.new do |s|
|
|
81
93
|
s.specification_version = 3
|
82
94
|
|
83
95
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
84
|
-
s.add_runtime_dependency(%q<unicorn-cuba-base>, ["~> 1.1.
|
96
|
+
s.add_runtime_dependency(%q<unicorn-cuba-base>, ["~> 1.1.2"])
|
85
97
|
s.add_runtime_dependency(%q<httpthumbnailer-client>, ["~> 1.1.1"])
|
86
98
|
s.add_runtime_dependency(%q<aws-sdk>, ["~> 1.10"])
|
87
99
|
s.add_runtime_dependency(%q<mime-types>, ["~> 1.17"])
|
@@ -96,7 +108,7 @@ Gem::Specification.new do |s|
|
|
96
108
|
s.add_development_dependency(%q<prawn>, ["= 0.8.4"])
|
97
109
|
s.add_development_dependency(%q<httpthumbnailer>, [">= 0"])
|
98
110
|
else
|
99
|
-
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.1.
|
111
|
+
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.1.2"])
|
100
112
|
s.add_dependency(%q<httpthumbnailer-client>, ["~> 1.1.1"])
|
101
113
|
s.add_dependency(%q<aws-sdk>, ["~> 1.10"])
|
102
114
|
s.add_dependency(%q<mime-types>, ["~> 1.17"])
|
@@ -112,7 +124,7 @@ Gem::Specification.new do |s|
|
|
112
124
|
s.add_dependency(%q<httpthumbnailer>, [">= 0"])
|
113
125
|
end
|
114
126
|
else
|
115
|
-
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.1.
|
127
|
+
s.add_dependency(%q<unicorn-cuba-base>, ["~> 1.1.2"])
|
116
128
|
s.add_dependency(%q<httpthumbnailer-client>, ["~> 1.1.1"])
|
117
129
|
s.add_dependency(%q<aws-sdk>, ["~> 1.10"])
|
118
130
|
s.add_dependency(%q<mime-types>, ["~> 1.17"])
|
@@ -66,12 +66,11 @@ module Configuration
|
|
66
66
|
request_state[name] = request_state.generate_meta_variable(name) or raise VariableNotDefinedError.new(name)
|
67
67
|
end
|
68
68
|
|
69
|
-
merge! query_string
|
70
69
|
self[:path] = path
|
71
70
|
merge! matches
|
72
71
|
self[:query_string_options] = query_string.sort.map{|kv| kv.join(':')}.join(',')
|
73
72
|
|
74
|
-
log.debug "processing request with body length: #{body.bytesize} bytes and variables: #{
|
73
|
+
log.debug "processing request with body length: #{body.bytesize} bytes and variables: #{map{|k,v| "#{k}: '#{v}'"}.join(', ')}"
|
75
74
|
|
76
75
|
@body = body
|
77
76
|
@images = Images.new(memory_limit)
|
@@ -177,14 +176,6 @@ module Configuration
|
|
177
176
|
end
|
178
177
|
end
|
179
178
|
|
180
|
-
class OutputOK
|
181
|
-
def realize(request_state)
|
182
|
-
request_state.output do
|
183
|
-
write_plain 200, 'OK'
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
179
|
class InclusionMatcher
|
189
180
|
def initialize(value, template)
|
190
181
|
@value = value
|
@@ -259,13 +250,28 @@ module Configuration
|
|
259
250
|
end
|
260
251
|
|
261
252
|
class Matcher
|
262
|
-
def initialize(
|
263
|
-
@
|
253
|
+
def initialize(names, debug_type = '', debug_value = '', &matcher)
|
254
|
+
@names = names
|
264
255
|
@matcher = matcher
|
256
|
+
@debug_type = debug_type
|
257
|
+
@debug_value = case debug_value
|
258
|
+
when Regexp
|
259
|
+
"/#{debug_value.source}/"
|
260
|
+
else
|
261
|
+
debug_value.inspect
|
262
|
+
end
|
265
263
|
end
|
266
264
|
|
267
|
-
attr_reader :
|
265
|
+
attr_reader :names
|
268
266
|
attr_reader :matcher
|
267
|
+
|
268
|
+
def to_s
|
269
|
+
if @names.empty?
|
270
|
+
"#{@debug_type}(#{@debug_value})"
|
271
|
+
else
|
272
|
+
"#{@debug_type}(#{@names.join(',')} => #{@debug_value})"
|
273
|
+
end
|
274
|
+
end
|
269
275
|
end
|
270
276
|
|
271
277
|
class Handler < Scope
|
@@ -280,7 +286,7 @@ module Configuration
|
|
280
286
|
end
|
281
287
|
|
282
288
|
def self.parse(configuration, node)
|
283
|
-
handler_configuration =
|
289
|
+
handler_configuration =
|
284
290
|
Struct.new(
|
285
291
|
:global,
|
286
292
|
:http_method,
|
@@ -295,45 +301,64 @@ module Configuration
|
|
295
301
|
handler_configuration.http_method = node.name
|
296
302
|
handler_configuration.uri_matchers = node.values.map do |matcher|
|
297
303
|
case matcher
|
298
|
-
# URI
|
304
|
+
# URI matchers
|
299
305
|
when %r{^:([^/]+)/(.*)/$} # :foobar/.*/
|
300
|
-
name = $1
|
301
|
-
|
302
|
-
|
303
|
-
|
306
|
+
name = $1.to_sym
|
307
|
+
_regexp = Regexp.new($2)
|
308
|
+
regexp = Regexp.new("(#{$2})")
|
309
|
+
Matcher.new([name], 'Regexp', _regexp) do
|
310
|
+
regexp
|
311
|
+
end
|
312
|
+
when %r{^/(.*)/$} # /.*/
|
313
|
+
regexp = $1
|
314
|
+
_regexp = Regexp.new($1)
|
315
|
+
names = Regexp.new($1).names.map{|n| n.to_sym}
|
316
|
+
Matcher.new(names, 'Regexp', _regexp) do
|
317
|
+
-> {
|
318
|
+
matchdata = env["PATH_INFO"].match(/\A\/(?<_match_>#{regexp})(?<_tail_>(?:\/|\z))/)
|
319
|
+
|
320
|
+
next false unless matchdata
|
321
|
+
|
322
|
+
path, *vars = matchdata.captures
|
323
|
+
|
324
|
+
env["SCRIPT_NAME"] += "/#{path}"
|
325
|
+
env["PATH_INFO"] = "#{vars.pop}#{matchdata.post_match}"
|
326
|
+
|
327
|
+
captures.push(*vars)
|
328
|
+
}
|
304
329
|
end
|
305
330
|
when /^:(.+)\?(.*)$/ # :foo?bar
|
306
331
|
name = $1.to_sym
|
307
332
|
default = $2
|
308
|
-
Matcher.new(name) do
|
333
|
+
Matcher.new([name], 'SegmentDefault', "<segment>|#{default}") do
|
309
334
|
->{match(name) || captures.push(default)}
|
310
335
|
end
|
311
336
|
when /^:(.+)$/ # :foobar
|
312
337
|
name = $1.to_sym
|
313
|
-
Matcher.new(name) do
|
338
|
+
Matcher.new([name], 'Segment', '<segment>') do
|
314
339
|
name
|
315
340
|
end
|
316
341
|
# Query string matchers
|
317
342
|
when /^\&([^=]+)=(.+)$/# ?foo=bar
|
318
|
-
name = $1
|
343
|
+
name = $1.to_sym
|
319
344
|
value = $2
|
320
|
-
Matcher.new(
|
321
|
-
->{req[name] && req[name] == value}
|
345
|
+
Matcher.new([name], 'QueryKeyValue', "#{name}=#{value}") do
|
346
|
+
->{req[name] && req[name] == value && captures.push(req[name])}
|
322
347
|
end
|
323
348
|
when /^\&:(.+)\?(.*)$/# &:foo?bar
|
324
|
-
name = $1
|
349
|
+
name = $1.to_sym
|
325
350
|
default = $2
|
326
|
-
Matcher.new(name
|
351
|
+
Matcher.new([name], 'QueryKeyDefault', "#{name}=<key>|#{default}") do
|
327
352
|
->{captures.push(req[name] || default)}
|
328
353
|
end
|
329
354
|
when /^\&:(.+)$/# &:foo
|
330
|
-
name = $1
|
331
|
-
Matcher.new(name
|
355
|
+
name = $1.to_sym
|
356
|
+
Matcher.new([name], 'QueryKey', "#{name}=<key>") do
|
332
357
|
->{req[name] && captures.push(req[name])}
|
333
358
|
end
|
334
|
-
#
|
359
|
+
# Literal URI segment matcher
|
335
360
|
else # foobar
|
336
|
-
Matcher.new(
|
361
|
+
Matcher.new([], "Literal", matcher) do
|
337
362
|
Regexp.escape(matcher)
|
338
363
|
end
|
339
364
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'httpimagestore/configuration/handler'
|
2
|
+
require 'httpimagestore/ruby_string_template'
|
2
3
|
|
3
4
|
module Configuration
|
4
5
|
class StorePathNotSetForImage < ConfigurationError
|
@@ -13,6 +14,53 @@ module Configuration
|
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
17
|
+
class OutputText
|
18
|
+
def self.match(node)
|
19
|
+
node.name == 'output_text'
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parse(configuration, node)
|
23
|
+
configuration.output and raise StatementCollisionError.new(node, 'output')
|
24
|
+
text = node.grab_values('text').first
|
25
|
+
status, cache_control = *node.grab_attributes('status', 'cache-control')
|
26
|
+
configuration.output = OutputText.new(text, status || 200, cache_control)
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(text, status, cache_control)
|
30
|
+
@text = RubyStringTemplate.new(text || fail("no text?!"))
|
31
|
+
@status = status || 200
|
32
|
+
@cache_control = cache_control
|
33
|
+
end
|
34
|
+
|
35
|
+
def realize(request_state)
|
36
|
+
# make sure variables are available in request context
|
37
|
+
status = @status
|
38
|
+
text = @text.render(request_state)
|
39
|
+
cache_control = @cache_control
|
40
|
+
request_state.output do
|
41
|
+
res['Cache-Control'] = cache_control if cache_control
|
42
|
+
write_plain status.to_i, text.to_s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class OutputOK < OutputText
|
48
|
+
def self.match(node)
|
49
|
+
node.name == 'output_ok'
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.parse(configuration, node)
|
53
|
+
configuration.output and raise StatementCollisionError.new(node, 'output')
|
54
|
+
cache_control = node.grab_attributes('cache-control').first
|
55
|
+
configuration.output = OutputOK.new(cache_control)
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize(cache_control = nil)
|
59
|
+
super 'OK', 200, cache_control
|
60
|
+
end
|
61
|
+
end
|
62
|
+
Handler::register_node_parser OutputText
|
63
|
+
|
16
64
|
class OutputMultiBase
|
17
65
|
class ImageName < String
|
18
66
|
include ConditionalInclusion
|
@@ -39,7 +87,8 @@ module Configuration
|
|
39
87
|
@names = names
|
40
88
|
end
|
41
89
|
end
|
42
|
-
|
90
|
+
Handler::register_node_parser OutputOK
|
91
|
+
|
43
92
|
class OutputImage
|
44
93
|
include ClassLogging
|
45
94
|
|
@@ -61,7 +110,7 @@ module Configuration
|
|
61
110
|
|
62
111
|
def realize(request_state)
|
63
112
|
image = request_state.images[@name]
|
64
|
-
mime_type =
|
113
|
+
mime_type =
|
65
114
|
if image.mime_type
|
66
115
|
image.mime_type
|
67
116
|
else
|
@@ -28,10 +28,10 @@ describe Configuration do
|
|
28
28
|
subject.handlers.length.should == 3
|
29
29
|
|
30
30
|
subject.handlers[0].http_method.should == 'get'
|
31
|
-
subject.handlers[0].uri_matchers.map{|m| m.
|
31
|
+
subject.handlers[0].uri_matchers.map{|m| m.names}.flatten.should == [:operation, :width, :height, :options]
|
32
32
|
|
33
33
|
subject.handlers[1].http_method.should == 'put'
|
34
|
-
subject.handlers[1].uri_matchers.map{|m| m.
|
34
|
+
subject.handlers[1].uri_matchers.map{|m| m.names}.flatten.should == [:test]
|
35
35
|
|
36
36
|
subject.handlers[2].http_method.should == 'post'
|
37
37
|
subject.handlers[2].uri_matchers.should be_empty
|
@@ -62,11 +62,6 @@ describe Configuration do
|
|
62
62
|
subject[:path].should == '/hello/world.jpg'
|
63
63
|
end
|
64
64
|
|
65
|
-
it 'should provide query string params' do
|
66
|
-
subject[:width].should == '123'
|
67
|
-
subject[:height].should == '321'
|
68
|
-
end
|
69
|
-
|
70
65
|
it 'should provide matches' do
|
71
66
|
subject[:operation].should == 'pad'
|
72
67
|
end
|
@@ -149,7 +144,7 @@ describe Configuration do
|
|
149
144
|
subject[:input_digest]
|
150
145
|
}.to raise_error Configuration::NoRequestBodyToGenerateMetaVariableError, %q{need not empty request body to generate value for 'input_digest'}
|
151
146
|
end
|
152
|
-
|
147
|
+
|
153
148
|
it 'should raise ImageNotLoadedError when asking for image related variable of not loaded image' do
|
154
149
|
expect {
|
155
150
|
subject.with_locals(image_name: 'abc')[:image_mime_extension]
|
@@ -202,7 +197,7 @@ describe Configuration do
|
|
202
197
|
limit.borrow 1
|
203
198
|
request_state.images['test'] = Configuration::Image.new('x')
|
204
199
|
limit.limit.should == 1
|
205
|
-
|
200
|
+
|
206
201
|
limit.borrow 1
|
207
202
|
limit.limit.should == 0
|
208
203
|
request_state.images['test'] = Configuration::Image.new('x')
|
@@ -255,19 +250,6 @@ describe Configuration do
|
|
255
250
|
subject.handlers[1].output.should be_a Configuration::OutputOK
|
256
251
|
subject.handlers[2].output.should be_a Configuration::OutputOK
|
257
252
|
end
|
258
|
-
|
259
|
-
describe Configuration::OutputOK do
|
260
|
-
it 'should output 200 with OK text/plain message when realized' do
|
261
|
-
state = Configuration::RequestState.new('abc')
|
262
|
-
subject.handlers[2].output.realize(state)
|
263
|
-
|
264
|
-
env = CubaResponseEnv.new
|
265
|
-
env.instance_eval &state.output_callback
|
266
|
-
env.res.status.should == 200
|
267
|
-
env.res.data.should == "OK\r\n"
|
268
|
-
env.res['Content-Type'].should == 'text/plain'
|
269
|
-
end
|
270
|
-
end
|
271
253
|
end
|
272
254
|
end
|
273
255
|
end
|
@@ -17,6 +17,91 @@ describe Configuration do
|
|
17
17
|
CubaResponseEnv.new
|
18
18
|
end
|
19
19
|
|
20
|
+
describe Configuration::OutputText do
|
21
|
+
subject do
|
22
|
+
Configuration.read(<<-'EOF')
|
23
|
+
get "test" {
|
24
|
+
output_text "hello world"
|
25
|
+
}
|
26
|
+
get "test" {
|
27
|
+
output_text "bad stuff" status=500
|
28
|
+
}
|
29
|
+
get "test" {
|
30
|
+
output_text "welcome" cache-control="public"
|
31
|
+
}
|
32
|
+
get "test" {
|
33
|
+
output_text "test1: #{test1} test2: #{test2}"
|
34
|
+
}
|
35
|
+
EOF
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should output hello world with default 200 status' do
|
39
|
+
subject.handlers[0].output.realize(state)
|
40
|
+
env = CubaResponseEnv.new
|
41
|
+
env.instance_eval &state.output_callback
|
42
|
+
env.res.status.should == 200
|
43
|
+
env.res.data.should == "hello world\r\n"
|
44
|
+
env.res['Content-Type'].should == 'text/plain'
|
45
|
+
env.res['Cache-Control'].should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should output bad stuff with 500 status' do
|
49
|
+
subject.handlers[1].output.realize(state)
|
50
|
+
env = CubaResponseEnv.new
|
51
|
+
env.instance_eval &state.output_callback
|
52
|
+
env.res.status.should == 500
|
53
|
+
env.res.data.should == "bad stuff\r\n"
|
54
|
+
env.res['Content-Type'].should == 'text/plain'
|
55
|
+
env.res['Cache-Control'].should be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should output welcome with public cache control' do
|
59
|
+
subject.handlers[2].output.realize(state)
|
60
|
+
env = CubaResponseEnv.new
|
61
|
+
env.instance_eval &state.output_callback
|
62
|
+
env.res.status.should == 200
|
63
|
+
env.res.data.should == "welcome\r\n"
|
64
|
+
env.res['Content-Type'].should == 'text/plain'
|
65
|
+
env.res['Cache-Control'].should == 'public'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should output text interpolated with variable values' do
|
69
|
+
state = Configuration::RequestState.new
|
70
|
+
state[:test1] = 'abc'
|
71
|
+
state[:test2] = 'xyz'
|
72
|
+
|
73
|
+
subject.handlers[3].output.realize(state)
|
74
|
+
env = CubaResponseEnv.new
|
75
|
+
env.instance_eval &state.output_callback
|
76
|
+
env.res.data.should == "test1: abc test2: xyz\r\n"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe Configuration::OutputOK do
|
81
|
+
subject do
|
82
|
+
Configuration.read(<<-EOF)
|
83
|
+
put "test" {
|
84
|
+
output_ok
|
85
|
+
}
|
86
|
+
EOF
|
87
|
+
end
|
88
|
+
|
89
|
+
before :each do
|
90
|
+
subject.handlers[0].sources[0].realize(state)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should output 200 with OK text/plain message when realized' do
|
94
|
+
state = Configuration::RequestState.new('abc')
|
95
|
+
subject.handlers[0].output.realize(state)
|
96
|
+
|
97
|
+
env = CubaResponseEnv.new
|
98
|
+
env.instance_eval &state.output_callback
|
99
|
+
env.res.status.should == 200
|
100
|
+
env.res.data.should == "OK\r\n"
|
101
|
+
env.res['Content-Type'].should == 'text/plain'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
20
105
|
describe Configuration::OutputImage do
|
21
106
|
subject do
|
22
107
|
Configuration.read(<<-EOF)
|
@@ -270,7 +355,7 @@ describe Configuration do
|
|
270
355
|
env.res['Content-Type'].should == 'text/uri-list'
|
271
356
|
env.res.data.should == "file://test.out\r\nfile://test.out2\r\n"
|
272
357
|
end
|
273
|
-
|
358
|
+
|
274
359
|
describe 'conditional inclusion support' do
|
275
360
|
let :state do
|
276
361
|
Configuration::RequestState.new('abc', list: 'input,image2')
|
@@ -335,4 +420,3 @@ describe Configuration do
|
|
335
420
|
end
|
336
421
|
end
|
337
422
|
end
|
338
|
-
|