httpimagestore 1.7.0 → 1.8.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/Gemfile +2 -2
- data/Gemfile.lock +7 -7
- data/README.md +59 -4
- data/VERSION +1 -1
- data/features/compatibility.feature +3 -3
- data/features/encoding.feature +35 -0
- data/features/error-reporting.feature +11 -0
- data/features/rewrite.feature +122 -0
- data/features/s3-store-and-thumbnail.feature +4 -4
- data/features/step_definitions/httpimagestore_steps.rb +18 -6
- data/features/support/env.rb +11 -9
- data/httpimagestore.gemspec +12 -9
- data/lib/httpimagestore/configuration/file.rb +2 -2
- data/lib/httpimagestore/configuration/handler.rb +7 -3
- data/lib/httpimagestore/configuration/output.rb +55 -17
- data/lib/httpimagestore/configuration/s3.rb +12 -4
- data/spec/configuration_file_spec.rb +3 -4
- data/spec/configuration_handler_spec.rb +1 -2
- data/spec/configuration_identify_spec.rb +1 -2
- data/spec/configuration_output_spec.rb +289 -10
- data/spec/configuration_path_spec.rb +2 -3
- data/spec/configuration_s3_spec.rb +39 -38
- data/spec/configuration_source_failover_spec.rb +1 -1
- data/spec/configuration_spec.rb +1 -2
- data/spec/configuration_thumbnailer_spec.rb +1 -2
- data/spec/spec_helper.rb +15 -7
- data/spec/support/utf_string.txt +1 -0
- metadata +11 -8
|
@@ -69,9 +69,12 @@ module Configuration
|
|
|
69
69
|
attr_reader :image_name
|
|
70
70
|
attr_reader :path_spec
|
|
71
71
|
|
|
72
|
-
def initialize(global, image_name, path_spec, matcher)
|
|
72
|
+
def initialize(global, image_name, scheme, host, port, path_spec, matcher)
|
|
73
73
|
@global = global
|
|
74
74
|
@image_name = image_name
|
|
75
|
+
@scheme = scheme
|
|
76
|
+
@host = host
|
|
77
|
+
@port = port
|
|
75
78
|
@path_spec = path_spec
|
|
76
79
|
inclusion_matcher matcher
|
|
77
80
|
end
|
|
@@ -79,26 +82,42 @@ module Configuration
|
|
|
79
82
|
def store_path(request_state)
|
|
80
83
|
store_path = request_state.images[@image_name].store_path or raise StorePathNotSetForImage.new(@image_name)
|
|
81
84
|
return store_path unless @path_spec
|
|
82
|
-
rendered_path(store_path, request_state)
|
|
83
|
-
end
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
locals = {
|
|
87
|
+
image_name: @image_name,
|
|
88
|
+
path: store_path
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
rendered_path(request_state.with_locals(locals))
|
|
91
92
|
end
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
def store_url(request_state)
|
|
95
|
+
url = request_state.images[@image_name].store_url or raise StoreURLNotSetForImage.new(@image_name)
|
|
96
|
+
url = url.dup
|
|
94
97
|
|
|
95
|
-
def rendered_path(store_path, request_state)
|
|
96
|
-
path = @global.paths[@path_spec]
|
|
97
98
|
locals = {
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
image_name: @image_name,
|
|
100
|
+
path: URI.utf_decode(url.path),
|
|
101
|
+
url: url.to_s
|
|
100
102
|
}
|
|
101
|
-
|
|
103
|
+
locals[:scheme] = url.scheme if url.scheme
|
|
104
|
+
locals[:host] = url.host if url.host
|
|
105
|
+
locals[:port] = url.port if url.port
|
|
106
|
+
|
|
107
|
+
request_state = request_state.with_locals(locals)
|
|
108
|
+
|
|
109
|
+
# optional rewrites
|
|
110
|
+
url.scheme = request_state.render_template(@scheme) if @scheme
|
|
111
|
+
url.host = request_state.render_template(@host) if @host
|
|
112
|
+
url.port = request_state.render_template(@port).to_i if @port
|
|
113
|
+
url.path = URI.encode(rendered_path(request_state)).tap{|path| path.replace('/' + path) if path[0] != '/'} if @path_spec
|
|
114
|
+
|
|
115
|
+
url
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
def rendered_path(request_state)
|
|
120
|
+
Pathname.new(@global.paths[@path_spec].render(request_state)).cleanpath.to_s
|
|
102
121
|
end
|
|
103
122
|
end
|
|
104
123
|
|
|
@@ -106,9 +125,9 @@ module Configuration
|
|
|
106
125
|
nodes = node.values.empty? ? node.children : [node]
|
|
107
126
|
output_specs = nodes.map do |node|
|
|
108
127
|
image_name = node.grab_values('image name').first
|
|
109
|
-
path_spec, if_image_name_on = *node.grab_attributes('path', 'if-image-name-on')
|
|
128
|
+
scheme, host, port, path_spec, if_image_name_on = *node.grab_attributes('scheme', 'host', 'port', 'path', 'if-image-name-on')
|
|
110
129
|
matcher = InclusionMatcher.new(image_name, if_image_name_on)
|
|
111
|
-
OutputSpec.new(configuration.global, image_name, path_spec, matcher)
|
|
130
|
+
OutputSpec.new(configuration.global, image_name, scheme, host, port, path_spec, matcher)
|
|
112
131
|
end
|
|
113
132
|
|
|
114
133
|
configuration.output and raise StatementCollisionError.new(node, 'output')
|
|
@@ -214,5 +233,24 @@ module Configuration
|
|
|
214
233
|
end
|
|
215
234
|
end
|
|
216
235
|
Handler::register_node_parser OutputStoreURL
|
|
236
|
+
|
|
237
|
+
class OutputStoreURI < OutputMultiBase
|
|
238
|
+
def self.match(node)
|
|
239
|
+
node.name == 'output_store_uri'
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def realize(request_state)
|
|
243
|
+
urls = @output_specs.select do |output_spec|
|
|
244
|
+
output_spec.included?(request_state)
|
|
245
|
+
end.map do |output_spec|
|
|
246
|
+
output_spec.store_url(request_state).path
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
request_state.output do
|
|
250
|
+
write_url_list 200, urls
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
Handler::register_node_parser OutputStoreURI
|
|
217
255
|
end
|
|
218
256
|
|
|
@@ -177,11 +177,11 @@ module Configuration
|
|
|
177
177
|
end
|
|
178
178
|
|
|
179
179
|
def private_url
|
|
180
|
-
s3_object.url_for(:read, expires: 60 * 60 * 24 * 365 * 20)
|
|
180
|
+
s3_object.url_for(:read, expires: 60 * 60 * 24 * 365 * 20) # expire in 20 years
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
def public_url
|
|
184
|
-
s3_object.public_url
|
|
184
|
+
s3_object.public_url
|
|
185
185
|
end
|
|
186
186
|
|
|
187
187
|
def content_type
|
|
@@ -237,11 +237,19 @@ module Configuration
|
|
|
237
237
|
end
|
|
238
238
|
|
|
239
239
|
def private_url
|
|
240
|
-
@cache_file.header['private_url']
|
|
240
|
+
url = @cache_file.header['private_url'] and return URI(url)
|
|
241
|
+
dirty! :private_url
|
|
242
|
+
url = super
|
|
243
|
+
@cache_file.header['private_url'] = url.to_s
|
|
244
|
+
url
|
|
241
245
|
end
|
|
242
246
|
|
|
243
247
|
def public_url
|
|
244
|
-
@cache_file.header['public_url']
|
|
248
|
+
url = @cache_file.header['public_url'] and return URI(url)
|
|
249
|
+
dirty! :public_url
|
|
250
|
+
url = super
|
|
251
|
+
@cache_file.header['public_url'] = url.to_s
|
|
252
|
+
url
|
|
245
253
|
end
|
|
246
254
|
|
|
247
255
|
def content_type
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
require_relative 'spec_helper'
|
|
2
2
|
require 'httpimagestore/configuration'
|
|
3
|
-
Configuration::Scope.logger =
|
|
3
|
+
MemoryLimit.logger = Configuration::Scope.logger = RootLogger.new('/dev/null')
|
|
4
4
|
|
|
5
5
|
require 'httpimagestore/configuration/file'
|
|
6
6
|
require 'httpimagestore/configuration/output'
|
|
7
|
-
MemoryLimit.logger = Logger.new('/dev/null')
|
|
8
7
|
|
|
9
8
|
describe Configuration do
|
|
10
9
|
let :state do
|
|
@@ -54,7 +53,7 @@ describe Configuration do
|
|
|
54
53
|
subject.handlers[0].sources[0].realize(state)
|
|
55
54
|
|
|
56
55
|
state.images['original'].source_path.should == "test.in"
|
|
57
|
-
state.images['original'].source_url.should == "file
|
|
56
|
+
state.images['original'].source_url.to_s.should == "file:/test.in"
|
|
58
57
|
end
|
|
59
58
|
|
|
60
59
|
describe 'context locals' do
|
|
@@ -220,7 +219,7 @@ describe Configuration do
|
|
|
220
219
|
subject.handlers[0].stores[0].realize(state)
|
|
221
220
|
|
|
222
221
|
state.images['input'].store_path.should == "test.out"
|
|
223
|
-
state.images['input'].store_url.should == "file
|
|
222
|
+
state.images['input'].store_url.to_s.should == "file:/test.out"
|
|
224
223
|
end
|
|
225
224
|
|
|
226
225
|
describe 'conditional inclusion support' do
|
|
@@ -2,11 +2,10 @@ require_relative 'spec_helper'
|
|
|
2
2
|
require_relative 'support/cuba_response_env'
|
|
3
3
|
|
|
4
4
|
require 'httpimagestore/configuration'
|
|
5
|
-
Configuration::Scope.logger =
|
|
5
|
+
MemoryLimit.logger = Configuration::Scope.logger = RootLogger.new('/dev/null')
|
|
6
6
|
|
|
7
7
|
require 'httpimagestore/configuration/handler'
|
|
8
8
|
require 'httpimagestore/configuration/output'
|
|
9
|
-
MemoryLimit.logger = Logger.new('/dev/null')
|
|
10
9
|
|
|
11
10
|
describe Configuration do
|
|
12
11
|
describe Configuration::Handler do
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
require_relative 'spec_helper'
|
|
2
2
|
require 'httpimagestore/configuration'
|
|
3
|
-
Configuration::Scope.logger =
|
|
3
|
+
MemoryLimit.logger = Configuration::Scope.logger = RootLogger.new('/dev/null')
|
|
4
4
|
|
|
5
5
|
require 'httpimagestore/configuration/output'
|
|
6
6
|
require 'httpimagestore/configuration/thumbnailer'
|
|
7
7
|
require 'httpimagestore/configuration/identify'
|
|
8
|
-
MemoryLimit.logger = Logger.new('/dev/null')
|
|
9
8
|
|
|
10
9
|
describe Configuration do
|
|
11
10
|
describe 'identify' do
|
|
@@ -2,11 +2,10 @@ require_relative 'spec_helper'
|
|
|
2
2
|
require_relative 'support/cuba_response_env'
|
|
3
3
|
|
|
4
4
|
require 'httpimagestore/configuration'
|
|
5
|
-
Configuration::Scope.logger =
|
|
5
|
+
MemoryLimit.logger = Configuration::Scope.logger = RootLogger.new('/dev/null')
|
|
6
6
|
|
|
7
7
|
require 'httpimagestore/configuration/output'
|
|
8
8
|
require 'httpimagestore/configuration/file'
|
|
9
|
-
MemoryLimit.logger = Logger.new('/dev/null')
|
|
10
9
|
|
|
11
10
|
describe Configuration do
|
|
12
11
|
let :state do
|
|
@@ -159,6 +158,10 @@ describe Configuration do
|
|
|
159
158
|
end
|
|
160
159
|
|
|
161
160
|
describe 'output store paths and URLs' do
|
|
161
|
+
let :utf_string do
|
|
162
|
+
(support_dir + 'utf_string.txt').read.strip
|
|
163
|
+
end
|
|
164
|
+
|
|
162
165
|
let :in_file do
|
|
163
166
|
Pathname.new("/tmp/test.in")
|
|
164
167
|
end
|
|
@@ -179,8 +182,12 @@ describe Configuration do
|
|
|
179
182
|
Pathname.new('/tmp/abc/t e s t.out')
|
|
180
183
|
end
|
|
181
184
|
|
|
185
|
+
let :utf_test_file do
|
|
186
|
+
Pathname.new("/tmp/abc/#{utf_string}.out")
|
|
187
|
+
end
|
|
188
|
+
|
|
182
189
|
before :each do
|
|
183
|
-
test_file.dirname.mkdir
|
|
190
|
+
test_file.dirname.mkdir unless test_file.dirname.directory?
|
|
184
191
|
test_file.open('w'){|io| io.write('abc')}
|
|
185
192
|
space_test_file.open('w'){|io| io.write('abc')}
|
|
186
193
|
in_file.open('w'){|io| io.write('abc')}
|
|
@@ -191,6 +198,7 @@ describe Configuration do
|
|
|
191
198
|
after :each do
|
|
192
199
|
test_file.exist? and test_file.unlink
|
|
193
200
|
space_test_file.exist? and space_test_file.unlink
|
|
201
|
+
utf_test_file.exist? and utf_test_file.unlink
|
|
194
202
|
test_file.dirname.exist? and test_file.dirname.rmdir
|
|
195
203
|
out_file.unlink if out_file.exist?
|
|
196
204
|
out2_file.unlink if out2_file.exist?
|
|
@@ -391,7 +399,7 @@ describe Configuration do
|
|
|
391
399
|
|
|
392
400
|
env.instance_eval &state.output_callback
|
|
393
401
|
env.res['Content-Type'].should == 'text/uri-list'
|
|
394
|
-
env.res.data.should == "file
|
|
402
|
+
env.res.data.should == "file:/test.out\r\n"
|
|
395
403
|
end
|
|
396
404
|
|
|
397
405
|
it 'should provide multiple file store URLs' do
|
|
@@ -423,7 +431,7 @@ describe Configuration do
|
|
|
423
431
|
|
|
424
432
|
env.instance_eval &state.output_callback
|
|
425
433
|
env.res['Content-Type'].should == 'text/uri-list'
|
|
426
|
-
env.res.data.should == "file
|
|
434
|
+
env.res.data.should == "file:/test.out\r\nfile:/test.out2\r\n"
|
|
427
435
|
end
|
|
428
436
|
|
|
429
437
|
describe 'conditional inclusion support' do
|
|
@@ -468,12 +476,12 @@ describe Configuration do
|
|
|
468
476
|
|
|
469
477
|
env.instance_eval &state.output_callback
|
|
470
478
|
env.res['Content-Type'].should == 'text/uri-list'
|
|
471
|
-
env.res.data.should == "file
|
|
479
|
+
env.res.data.should == "file:/test.out1\r\nfile:/test.out3\r\n"
|
|
472
480
|
end
|
|
473
481
|
end
|
|
474
482
|
|
|
475
|
-
describe '
|
|
476
|
-
it 'should
|
|
483
|
+
describe 'URL rewrites' do
|
|
484
|
+
it 'should allow using path spec to rewrite URL path component' do
|
|
477
485
|
subject = Configuration.read(<<-'EOF')
|
|
478
486
|
path "out" "abc/test.out"
|
|
479
487
|
|
|
@@ -492,7 +500,93 @@ describe Configuration do
|
|
|
492
500
|
|
|
493
501
|
env.instance_eval &state.output_callback
|
|
494
502
|
env.res['Content-Type'].should == 'text/uri-list'
|
|
495
|
-
env.res.data.should == "file
|
|
503
|
+
env.res.data.should == "file:/hello/abc/world/test-xyz.out\r\n"
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
it 'should allow rewriting scheme component' do
|
|
507
|
+
subject = Configuration.read(<<-'EOF')
|
|
508
|
+
path "out" "abc/test.out"
|
|
509
|
+
|
|
510
|
+
post "single" {
|
|
511
|
+
store_file "input" root="/tmp" path="out"
|
|
512
|
+
|
|
513
|
+
output_store_url "input" scheme="ftp"
|
|
514
|
+
}
|
|
515
|
+
EOF
|
|
516
|
+
|
|
517
|
+
subject.handlers[0].sources[0].realize(state)
|
|
518
|
+
subject.handlers[0].stores[0].realize(state)
|
|
519
|
+
subject.handlers[0].output.realize(state)
|
|
520
|
+
|
|
521
|
+
env.instance_eval &state.output_callback
|
|
522
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
523
|
+
env.res.data.should == "ftp:/abc/test.out\r\n"
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
it 'should allow rewriting host component' do
|
|
527
|
+
subject = Configuration.read(<<-'EOF')
|
|
528
|
+
path "out" "abc/test.out"
|
|
529
|
+
|
|
530
|
+
post "single" {
|
|
531
|
+
store_file "input" root="/tmp" path="out"
|
|
532
|
+
|
|
533
|
+
output_store_url "input" host="localhost"
|
|
534
|
+
}
|
|
535
|
+
EOF
|
|
536
|
+
|
|
537
|
+
subject.handlers[0].sources[0].realize(state)
|
|
538
|
+
subject.handlers[0].stores[0].realize(state)
|
|
539
|
+
subject.handlers[0].output.realize(state)
|
|
540
|
+
|
|
541
|
+
env.instance_eval &state.output_callback
|
|
542
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
543
|
+
env.res.data.should == "file://localhost/abc/test.out\r\n"
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
it 'should allow rewriting port component' do
|
|
547
|
+
subject = Configuration.read(<<-'EOF')
|
|
548
|
+
path "out" "abc/test.out"
|
|
549
|
+
|
|
550
|
+
post "single" {
|
|
551
|
+
store_file "input" root="/tmp" path="out"
|
|
552
|
+
|
|
553
|
+
output_store_url "input" port="21"
|
|
554
|
+
}
|
|
555
|
+
EOF
|
|
556
|
+
|
|
557
|
+
subject.handlers[0].sources[0].realize(state)
|
|
558
|
+
subject.handlers[0].stores[0].realize(state)
|
|
559
|
+
subject.handlers[0].output.realize(state)
|
|
560
|
+
|
|
561
|
+
env.instance_eval &state.output_callback
|
|
562
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
563
|
+
env.res.data.should == "file::21/abc/test.out\r\n"
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
it 'should allow using variables for all supported rewrites' do
|
|
567
|
+
state = Configuration::RequestState.new('abc',
|
|
568
|
+
remote: 'example.com',
|
|
569
|
+
remote_port: 21,
|
|
570
|
+
proto: 'ftp'
|
|
571
|
+
)
|
|
572
|
+
subject = Configuration.read(<<-'EOF')
|
|
573
|
+
path "out" "abc/test.out"
|
|
574
|
+
path "formatted" "hello/#{dirname}/world/#{basename}-xyz.#{extension}"
|
|
575
|
+
|
|
576
|
+
post "single" {
|
|
577
|
+
store_file "input" root="/tmp" path="out"
|
|
578
|
+
|
|
579
|
+
output_store_url "input" scheme="#{proto}" host="#{remote}" port="#{remote_port}" path="formatted"
|
|
580
|
+
}
|
|
581
|
+
EOF
|
|
582
|
+
|
|
583
|
+
subject.handlers[0].sources[0].realize(state)
|
|
584
|
+
subject.handlers[0].stores[0].realize(state)
|
|
585
|
+
subject.handlers[0].output.realize(state)
|
|
586
|
+
|
|
587
|
+
env.instance_eval &state.output_callback
|
|
588
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
589
|
+
env.res.data.should == "ftp://example.com:21/hello/abc/world/test-xyz.out\r\n"
|
|
496
590
|
end
|
|
497
591
|
end
|
|
498
592
|
|
|
@@ -518,7 +612,7 @@ describe Configuration do
|
|
|
518
612
|
|
|
519
613
|
env.instance_eval &state.output_callback
|
|
520
614
|
env.res['Content-Type'].should == 'text/uri-list'
|
|
521
|
-
env.res.data.should == "file
|
|
615
|
+
env.res.data.should == "file:/abc/t%20e%20s%20t.out\r\nfile:/hello/abc/world/t%20e%20s%20t-xyz.out\r\n"
|
|
522
616
|
end
|
|
523
617
|
end
|
|
524
618
|
|
|
@@ -538,5 +632,190 @@ describe Configuration do
|
|
|
538
632
|
end
|
|
539
633
|
end
|
|
540
634
|
end
|
|
635
|
+
|
|
636
|
+
describe Configuration::OutputStoreURI do
|
|
637
|
+
it 'should provide file store URI' do
|
|
638
|
+
subject = Configuration.read(<<-EOF)
|
|
639
|
+
path {
|
|
640
|
+
"out" "test.out"
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
post "single" {
|
|
644
|
+
store_file "input" root="/tmp" path="out"
|
|
645
|
+
|
|
646
|
+
output_store_uri "input"
|
|
647
|
+
}
|
|
648
|
+
EOF
|
|
649
|
+
|
|
650
|
+
subject.handlers[0].sources[0].realize(state)
|
|
651
|
+
subject.handlers[0].stores[0].realize(state)
|
|
652
|
+
subject.handlers[0].output.realize(state)
|
|
653
|
+
|
|
654
|
+
env.instance_eval &state.output_callback
|
|
655
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
656
|
+
env.res.data.should == "/test.out\r\n"
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
it 'should provide multiple file store URIs' do
|
|
660
|
+
subject = Configuration.read(<<-EOF)
|
|
661
|
+
path {
|
|
662
|
+
"in" "test.in"
|
|
663
|
+
"out" "test.out"
|
|
664
|
+
"out2" "test.out2"
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
post "multi" {
|
|
668
|
+
source_file "original" root="/tmp" path="in"
|
|
669
|
+
|
|
670
|
+
store_file "input" root="/tmp" path="out"
|
|
671
|
+
store_file "original" root="/tmp" path="out2"
|
|
672
|
+
|
|
673
|
+
output_store_uri {
|
|
674
|
+
"input"
|
|
675
|
+
"original"
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
EOF
|
|
679
|
+
|
|
680
|
+
subject.handlers[0].sources[0].realize(state)
|
|
681
|
+
subject.handlers[0].sources[1].realize(state)
|
|
682
|
+
subject.handlers[0].stores[0].realize(state)
|
|
683
|
+
subject.handlers[0].stores[1].realize(state)
|
|
684
|
+
subject.handlers[0].output.realize(state)
|
|
685
|
+
|
|
686
|
+
env.instance_eval &state.output_callback
|
|
687
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
688
|
+
env.res.data.should == "/test.out\r\n/test.out2\r\n"
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
describe 'conditional inclusion support' do
|
|
692
|
+
let :state do
|
|
693
|
+
Configuration::RequestState.new('abc', list: 'input,image2')
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
subject do
|
|
697
|
+
Configuration.read(<<-'EOF')
|
|
698
|
+
path {
|
|
699
|
+
"in" "test.in"
|
|
700
|
+
"out1" "test.out1"
|
|
701
|
+
"out2" "test.out2"
|
|
702
|
+
"out3" "test.out3"
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
post "multi" {
|
|
706
|
+
source_file "image1" root="/tmp" path="in"
|
|
707
|
+
source_file "image2" root="/tmp" path="in"
|
|
708
|
+
|
|
709
|
+
store_file "input" root="/tmp" path="out1"
|
|
710
|
+
store_file "image1" root="/tmp" path="out2"
|
|
711
|
+
store_file "image2" root="/tmp" path="out3"
|
|
712
|
+
|
|
713
|
+
output_store_uri {
|
|
714
|
+
"input" if-image-name-on="#{list}"
|
|
715
|
+
"image1" if-image-name-on="#{list}"
|
|
716
|
+
"image2" if-image-name-on="#{list}"
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
EOF
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
it 'should output store url only for images that names match if-image-name-on list' do
|
|
723
|
+
subject.handlers[0].sources[0].realize(state)
|
|
724
|
+
subject.handlers[0].sources[1].realize(state)
|
|
725
|
+
subject.handlers[0].sources[2].realize(state)
|
|
726
|
+
subject.handlers[0].stores[0].realize(state)
|
|
727
|
+
subject.handlers[0].stores[1].realize(state)
|
|
728
|
+
subject.handlers[0].stores[2].realize(state)
|
|
729
|
+
subject.handlers[0].output.realize(state)
|
|
730
|
+
|
|
731
|
+
env.instance_eval &state.output_callback
|
|
732
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
733
|
+
env.res.data.should == "/test.out1\r\n/test.out3\r\n"
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
describe 'URI rewrites' do
|
|
738
|
+
it 'should allow using path spec to rewrite URI path' do
|
|
739
|
+
subject = Configuration.read(<<-'EOF')
|
|
740
|
+
path "out" "abc/test.out"
|
|
741
|
+
|
|
742
|
+
path "formatted" "hello/#{dirname}/world/#{basename}-xyz.#{extension}"
|
|
743
|
+
|
|
744
|
+
post "single" {
|
|
745
|
+
store_file "input" root="/tmp" path="out"
|
|
746
|
+
|
|
747
|
+
output_store_uri "input" path="formatted"
|
|
748
|
+
}
|
|
749
|
+
EOF
|
|
750
|
+
|
|
751
|
+
subject.handlers[0].sources[0].realize(state)
|
|
752
|
+
subject.handlers[0].stores[0].realize(state)
|
|
753
|
+
subject.handlers[0].output.realize(state)
|
|
754
|
+
|
|
755
|
+
env.instance_eval &state.output_callback
|
|
756
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
757
|
+
env.res.data.should == "/hello/abc/world/test-xyz.out\r\n"
|
|
758
|
+
end
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
describe 'URI encoding' do
|
|
762
|
+
let :subject do
|
|
763
|
+
Configuration.read(<<-'EOF')
|
|
764
|
+
path "out" "abc/#{name}.out"
|
|
765
|
+
path "formatted" "hello/#{dirname}/world/#{basename}-xyz.#{extension}"
|
|
766
|
+
|
|
767
|
+
post "single" {
|
|
768
|
+
store_file "input" root="/tmp" path="out"
|
|
769
|
+
|
|
770
|
+
output_store_uri {
|
|
771
|
+
"input"
|
|
772
|
+
"input" path="formatted"
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
EOF
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
it 'should provide properly encoded file store URI' do
|
|
779
|
+
state = Configuration::RequestState.new('abc', name: 't e s t')
|
|
780
|
+
|
|
781
|
+
subject.handlers[0].sources[0].realize(state)
|
|
782
|
+
subject.handlers[0].stores[0].realize(state)
|
|
783
|
+
subject.handlers[0].output.realize(state)
|
|
784
|
+
|
|
785
|
+
env.instance_eval &state.output_callback
|
|
786
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
787
|
+
env.res.data.should == "/abc/t%20e%20s%20t.out\r\n/hello/abc/world/t%20e%20s%20t-xyz.out\r\n"
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
it 'should handle UTF-8 characters' do
|
|
791
|
+
state = Configuration::RequestState.new('abc', name: utf_string)
|
|
792
|
+
subject.handlers[0].sources[0].realize(state)
|
|
793
|
+
subject.handlers[0].stores[0].realize(state)
|
|
794
|
+
subject.handlers[0].output.realize(state)
|
|
795
|
+
|
|
796
|
+
env.instance_eval &state.output_callback
|
|
797
|
+
env.res['Content-Type'].should == 'text/uri-list'
|
|
798
|
+
l1, l2 = *env.res.data.split("\r\n")
|
|
799
|
+
URI.utf_decode(l1).should == "/abc/#{utf_string}.out"
|
|
800
|
+
URI.utf_decode(l2).should == "/hello/abc/world/#{utf_string}-xyz.out"
|
|
801
|
+
end
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
describe 'error handling' do
|
|
805
|
+
it 'should raise StoreURLNotSetForImage for output of not stored image' do
|
|
806
|
+
subject = Configuration.read(<<-EOF)
|
|
807
|
+
post "single" {
|
|
808
|
+
output_store_uri "input"
|
|
809
|
+
}
|
|
810
|
+
EOF
|
|
811
|
+
|
|
812
|
+
subject.handlers[0].sources[0].realize(state)
|
|
813
|
+
|
|
814
|
+
expect {
|
|
815
|
+
subject.handlers[0].output.realize(state)
|
|
816
|
+
}.to raise_error Configuration::StoreURLNotSetForImage, %{store URL not set for image 'input'}
|
|
817
|
+
end
|
|
818
|
+
end
|
|
819
|
+
end
|
|
541
820
|
end
|
|
542
821
|
end
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
require_relative 'spec_helper'
|
|
2
2
|
require 'httpimagestore/configuration'
|
|
3
|
-
Configuration::Scope.logger =
|
|
3
|
+
MemoryLimit.logger = Configuration::Scope.logger = RootLogger.new('/dev/null')
|
|
4
4
|
|
|
5
5
|
require 'httpimagestore/configuration/handler'
|
|
6
6
|
require 'httpimagestore/configuration/path'
|
|
7
|
-
MemoryLimit.logger = Logger.new('/dev/null')
|
|
8
7
|
|
|
9
8
|
describe Configuration do
|
|
10
9
|
describe 'path rendering' do
|
|
@@ -62,7 +61,7 @@ describe Configuration do
|
|
|
62
61
|
|
|
63
62
|
expect {
|
|
64
63
|
subject.paths['test'].render
|
|
65
|
-
}.to raise_error Configuration::NoValueForPathTemplatePlaceholerError, %q{cannot generate path 'test' from template '#{abc}#{xyz}': no value for '#{abc}'}
|
|
64
|
+
}.to raise_error Configuration::NoValueForPathTemplatePlaceholerError, %q{cannot generate path 'test' from template '#{abc}#{xyz}': no value for '#{abc}'}
|
|
66
65
|
end
|
|
67
66
|
end
|
|
68
67
|
|