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
@@ -8,18 +8,18 @@ Feature: S3 object Cache-Control header settings
|
|
8
8
|
"""
|
9
9
|
s3 key="@AWS_ACCESS_KEY_ID@" secret="@AWS_SECRET_ACCESS_KEY@" ssl=false
|
10
10
|
|
11
|
-
path "hash"
|
12
|
-
path "hash-name"
|
11
|
+
path "hash" "#{input_digest}.#{image_mime_extension}"
|
12
|
+
path "hash-name" "#{input_digest}-#{image_name}.#{image_mime_extension}"
|
13
13
|
|
14
14
|
put "thumbnail" {
|
15
15
|
thumbnail "input" {
|
16
|
-
"no-cache"
|
17
|
-
"cache"
|
16
|
+
"no-cache" operation="crop" width=128 height=128 format="jpeg"
|
17
|
+
"cache" operation="crop" width=256 height=256 format="jpeg"
|
18
18
|
}
|
19
19
|
|
20
|
-
store_s3 "input"
|
21
|
-
store_s3 "no-cache"
|
22
|
-
store_s3 "cache"
|
20
|
+
store_s3 "input" bucket="@AWS_S3_TEST_BUCKET@" public=true path="hash"
|
21
|
+
store_s3 "no-cache" bucket="@AWS_S3_TEST_BUCKET@" public=true path="hash-name"
|
22
|
+
store_s3 "cache" bucket="@AWS_S3_TEST_BUCKET@" public=true path="hash-name" cache-control="public, max-age=31557600, s-maxage=0"
|
23
23
|
}
|
24
24
|
"""
|
25
25
|
|
@@ -38,5 +38,4 @@ Feature: S3 object Cache-Control header settings
|
|
38
38
|
"""
|
39
39
|
And http://@AWS_S3_TEST_BUCKET@.s3.amazonaws.com/4006450256177f4a.jpg Cache-Control header will not be set
|
40
40
|
And http://@AWS_S3_TEST_BUCKET@.s3.amazonaws.com/4006450256177f4a-no-cache.jpg Cache-Control header will not be set
|
41
|
-
And http://@AWS_S3_TEST_BUCKET@.s3.amazonaws.com/4006450256177f4a-cache.jpg Cache-Control header will be public, max-age=31557600, s-maxage=0
|
42
|
-
|
41
|
+
And http://@AWS_S3_TEST_BUCKET@.s3.amazonaws.com/4006450256177f4a-cache.jpg Cache-Control header will be public, max-age=31557600, s-maxage=0
|
@@ -9,49 +9,63 @@ Feature: Image list based thumbnailing and S3 storage
|
|
9
9
|
"""
|
10
10
|
s3 key="@AWS_ACCESS_KEY_ID@" secret="@AWS_SECRET_ACCESS_KEY@" ssl=false
|
11
11
|
|
12
|
-
path "hash"
|
13
|
-
path "hash-name"
|
14
|
-
path "structured"
|
15
|
-
path "structured-name"
|
12
|
+
path "hash" "#{input_digest}.#{image_mime_extension}"
|
13
|
+
path "hash-name" "#{input_digest}/#{image_name}.#{image_mime_extension}"
|
14
|
+
path "structured" "#{dirname}/#{input_digest}/#{basename}.#{image_mime_extension}"
|
15
|
+
path "structured-name" "#{dirname}/#{input_digest}/#{basename}-#{image_name}.#{image_mime_extension}"
|
16
|
+
path "flexi-original" "#{hash}.jpg"
|
16
17
|
|
17
18
|
put "thumbnail" ":name_list" ":path/.+/" {
|
18
19
|
thumbnail "input" {
|
19
|
-
"small"
|
20
|
-
"tiny_png"
|
21
|
-
"bad"
|
20
|
+
"small" operation="crop" width=128 height=128 format="jpeg" if-image-name-on="#{name_list}"
|
21
|
+
"tiny_png" operation="crop" width=32 height=32 format="png" if-image-name-on="#{name_list}"
|
22
|
+
"bad" operation="crop" width=0 height=0 if-image-name-on="#{name_list}"
|
22
23
|
}
|
23
24
|
|
24
|
-
store_s3 "input"
|
25
|
-
store_s3 "small"
|
26
|
-
store_s3 "tiny_png"
|
25
|
+
store_s3 "input" bucket="@AWS_S3_TEST_BUCKET@" path="structured" public=true
|
26
|
+
store_s3 "small" bucket="@AWS_S3_TEST_BUCKET@" path="structured-name" public=true if-image-name-on="#{name_list}"
|
27
|
+
store_s3 "tiny_png" bucket="@AWS_S3_TEST_BUCKET@" path="structured-name" public=true if-image-name-on="#{name_list}"
|
27
28
|
|
28
29
|
output_store_url {
|
29
30
|
"input"
|
30
|
-
"small"
|
31
|
-
"tiny_png"
|
31
|
+
"small" if-image-name-on="#{name_list}"
|
32
|
+
"tiny_png" if-image-name-on="#{name_list}"
|
32
33
|
}
|
33
34
|
}
|
34
35
|
|
35
36
|
put "thumbnail" ":name_list" {
|
36
37
|
thumbnail "input" {
|
37
|
-
"small"
|
38
|
-
"tiny_png"
|
38
|
+
"small" operation="crop" width=128 height=128 format="jpeg" if-image-name-on="#{name_list}"
|
39
|
+
"tiny_png" operation="crop" width=32 height=32 format="png" if-image-name-on="#{name_list}"
|
39
40
|
}
|
40
41
|
|
41
|
-
store_s3 "input"
|
42
|
-
store_s3 "small"
|
43
|
-
store_s3 "tiny_png"
|
42
|
+
store_s3 "input" bucket="@AWS_S3_TEST_BUCKET@" path="hash" public=true
|
43
|
+
store_s3 "small" bucket="@AWS_S3_TEST_BUCKET@" path="hash-name" public=true if-image-name-on="#{name_list}"
|
44
|
+
store_s3 "tiny_png" bucket="@AWS_S3_TEST_BUCKET@" path="hash-name" public=true if-image-name-on="#{name_list}"
|
44
45
|
|
45
46
|
output_store_url {
|
46
47
|
"input"
|
47
|
-
"small"
|
48
|
-
"tiny_png"
|
49
|
-
"bad"
|
48
|
+
"small" if-image-name-on="#{name_list}"
|
49
|
+
"tiny_png" if-image-name-on="#{name_list}"
|
50
|
+
"bad" if-image-name-on="#{name_list}"
|
50
51
|
}
|
51
52
|
}
|
53
|
+
|
54
|
+
# Forward compatible getting of thumbnails
|
55
|
+
get "thumbnail" ":hash/[0-f]{16}/" ":type/.*-square.jpg/" {
|
56
|
+
source_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="flexi-original"
|
57
|
+
thumbnail "original" "thumbnail" operation="crop" width="50" height="50"
|
58
|
+
output_image "thumbnail" cache-control="public, max-age=31557600, s-maxage=0"
|
59
|
+
}
|
60
|
+
|
61
|
+
get "thumbnail" ":hash/[0-f]{16}/" ":type/.*-normal.jpg/" {
|
62
|
+
source_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="flexi-original"
|
63
|
+
thumbnail "original" "thumbnail" operation="fit" width="100" height="2000"
|
64
|
+
output_image "thumbnail" cache-control="public, max-age=31557600, s-maxage=0"
|
65
|
+
}
|
52
66
|
"""
|
53
67
|
|
54
|
-
@compatibility
|
68
|
+
@compatibility
|
55
69
|
Scenario: Putting original and its thumbnails to S3 bucket
|
56
70
|
Given there is no 4006450256177f4a.jpg file in S3 bucket
|
57
71
|
And there is no 4006450256177f4a/small.jpg file in S3 bucket
|
@@ -127,3 +141,14 @@ Feature: Image list based thumbnailing and S3 storage
|
|
127
141
|
And http://@AWS_S3_TEST_BUCKET@.s3.amazonaws.com/test/图像/4006450256177f4a/测试.jpg will contain JPEG image of size 509x719
|
128
142
|
And http://@AWS_S3_TEST_BUCKET@.s3.amazonaws.com/test/图像/4006450256177f4a/测试-small.jpg will contain JPEG image of size 128x128
|
129
143
|
|
144
|
+
@compatibility @forward @test
|
145
|
+
Scenario: Getting thumbanils requested with compatibility API from flexi bucket
|
146
|
+
Given test.jpg file content is stored in S3 under 1234567890123456.jpg
|
147
|
+
When I do GET request http://localhost:3000/thumbnail/1234567890123456/foobar-blah-square.jpg
|
148
|
+
Then response status will be 200
|
149
|
+
And response content type will be image/jpeg
|
150
|
+
Then response body will contain JPEG image of size 50x50
|
151
|
+
When I do GET request http://localhost:3000/thumbnail/1234567890123456/foobar-blah-normal.jpg
|
152
|
+
Then response status will be 200
|
153
|
+
And response content type will be image/jpeg
|
154
|
+
Then response body will contain JPEG image of size 100x141
|
@@ -9,28 +9,28 @@ Feature: Image list based thumbnailing and S3 storage
|
|
9
9
|
"""
|
10
10
|
s3 key="@AWS_ACCESS_KEY_ID@" secret="@AWS_SECRET_ACCESS_KEY@" ssl=false
|
11
11
|
|
12
|
-
path "structured-name"
|
13
|
-
path "missing"
|
14
|
-
path "zero"
|
12
|
+
path "structured-name" "#{dirname}/#{input_digest}/#{basename}-#{image_name}.#{image_mime_extension}"
|
13
|
+
path "missing" "blah"
|
14
|
+
path "zero" "zero"
|
15
15
|
|
16
16
|
put "multipart" ":name_list" {
|
17
17
|
thumbnail "input" {
|
18
|
-
"small"
|
19
|
-
"bad"
|
20
|
-
"bad_dim"
|
21
|
-
"superlarge"
|
22
|
-
"large_png"
|
23
|
-
"bad_opts"
|
18
|
+
"small" operation="crop" width=128 height=128 if-image-name-on="#{name_list}"
|
19
|
+
"bad" operation="crop" width=0 height=0 if-image-name-on="#{name_list}"
|
20
|
+
"bad_dim" operation="crop" width="128x" height=128 if-image-name-on="#{name_list}"
|
21
|
+
"superlarge" operation="crop" width=16000 height=16000 if-image-name-on="#{name_list}"
|
22
|
+
"large_png" operation="crop" width=7000 height=7000 format="png" if-image-name-on="#{name_list}"
|
23
|
+
"bad_opts" operation="crop" width=128 height=128 options="foo=bar" if-image-name-on="#{name_list}"
|
24
24
|
}
|
25
25
|
}
|
26
26
|
|
27
27
|
put "singlepart" ":name_list" {
|
28
|
-
thumbnail "input"
|
29
|
-
thumbnail "input"
|
30
|
-
thumbnail "input"
|
31
|
-
thumbnail "input"
|
32
|
-
thumbnail "input"
|
33
|
-
thumbnail "input"
|
28
|
+
thumbnail "input" "small" operation="crop" width=128 height=128 if-image-name-on="#{name_list}"
|
29
|
+
thumbnail "input" "bad" operation="crop" width=0 height=0 if-image-name-on="#{name_list}"
|
30
|
+
thumbnail "input" "bad_dim" operation="crop" width="128x" height=128 if-image-name-on="#{name_list}"
|
31
|
+
thumbnail "input" "superlarge" operation="crop" width=16000 height=16000 if-image-name-on="#{name_list}"
|
32
|
+
thumbnail "input" "large_png" operation="crop" width=7000 height=7000 format="png" if-image-name-on="#{name_list}"
|
33
|
+
thumbnail "input" "bad_opts" operation="crop" width=128 height=128 options="foo=bar" if-image-name-on="#{name_list}"
|
34
34
|
}
|
35
35
|
|
36
36
|
get "s3" {
|
@@ -250,4 +250,3 @@ Feature: Image list based thumbnailing and S3 storage
|
|
250
250
|
"""
|
251
251
|
cannot generate path 'no_image_meta' from template '#{image_mime_extension}': image 'input' does not have data for variable 'image_mime_extension'
|
252
252
|
"""
|
253
|
-
|
data/features/flexi.feature
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Feature: Flexible API with two storage options and Facebook like thumbnailing URL format
|
2
|
-
Features two storage
|
2
|
+
Features two storage approaches: with JPEG conversion and limiting in size - for user provided content - and storing as is.
|
3
3
|
POST requests will end up with server side generated storage key based on input data digest.
|
4
|
-
PUT
|
5
|
-
Thumbnail GET API is
|
4
|
+
PUT requests can be used to store image under provided storage key.
|
5
|
+
Thumbnail GET API is similar to described in https://developers.facebook.com/docs/reference/api/using-pictures/#sizes.
|
6
6
|
Stored object extension and content type is determined from image data.
|
7
7
|
|
8
8
|
Background:
|
@@ -256,5 +256,4 @@ Feature: Flexible API with two storage options and Facebook like thumbnailing UR
|
|
256
256
|
And I do GET request http://localhost:3000/pictures/test.png?height=321
|
257
257
|
Then response status will be 200
|
258
258
|
And response content type will be image/png
|
259
|
-
Then response body will contain PNG image of size 227x321
|
260
|
-
|
259
|
+
Then response body will contain PNG image of size 227x321
|
@@ -0,0 +1,211 @@
|
|
1
|
+
Feature: Request matching
|
2
|
+
Incoming requests needs to be matched in flexible way and appropriate data needs to be available in form of variables used to parametrize processing.
|
3
|
+
|
4
|
+
Background:
|
5
|
+
Given httpthumbnailer server is running at http://localhost:3100/health_check
|
6
|
+
Given httpimagestore server is running at http://localhost:3000/health_check with the following configuration
|
7
|
+
"""
|
8
|
+
# URI segment matchers
|
9
|
+
get "string" {
|
10
|
+
output_text "path: '#{path}'"
|
11
|
+
}
|
12
|
+
|
13
|
+
get "any" "default" ":test1" ":test2?foo" ":test3?bar" ":test4?baz" {
|
14
|
+
output_text "test1: '#{test1}' test2: '#{test2}' test3: '#{test3}' test4: '#{test4}' path: '#{path}'"
|
15
|
+
}
|
16
|
+
get "any" ":test1" ":test2" {
|
17
|
+
output_text "test1: '#{test1}' test2: '#{test2}' path: '#{path}'"
|
18
|
+
}
|
19
|
+
|
20
|
+
get "regexp1" ":test1/a.c/" ":test2/.*/" {
|
21
|
+
output_text "test1: '#{test1}' test2: '#{test2}' path: '#{path}'"
|
22
|
+
}
|
23
|
+
get "regexp-404" ":test1/a.c.*/" ":test2/\\./" {
|
24
|
+
output_text "test1: '#{test1}' test2: '#{test2}' path: '#{path}'"
|
25
|
+
}
|
26
|
+
|
27
|
+
get "regexp" "named" "/(?<test1>..)-(?<test2>..)/" ":test3/.*/" {
|
28
|
+
output_text "test1: '#{test1}' test2: '#{test2}' test3: '#{test3}' path: '#{path}'"
|
29
|
+
}
|
30
|
+
get "regexp" "named" "nocapture" "/..-../" {
|
31
|
+
output_text "path: '#{path}'"
|
32
|
+
}
|
33
|
+
get "regexp" "named" "bad1" "/(?<test1>..)-(?<test1>..)/" ":test3/.*/" {
|
34
|
+
output_text "test1: '#{test1}' test2: '#{test2}' test3: '#{test3}' path: '#{path}'"
|
35
|
+
}
|
36
|
+
get "regexp" "named" "bad2" "/(?<test1>..)-(?<test1>..)/" ":test3/.*/" {
|
37
|
+
output_text "test1: '#{test1}' test3: '#{test3}' path: '#{path}'"
|
38
|
+
}
|
39
|
+
|
40
|
+
# Query string matchers
|
41
|
+
get "query" "key-value" "&hello=world" {
|
42
|
+
output_text "query key-value matched path: '#{path}'"
|
43
|
+
}
|
44
|
+
|
45
|
+
get "query" "key" "default" "&:hello?abc" {
|
46
|
+
output_text "key: '#{hello}' path: '#{path}'"
|
47
|
+
}
|
48
|
+
get "query" "key" "&:hello" {
|
49
|
+
output_text "key: '#{hello}' path: '#{path}'"
|
50
|
+
}
|
51
|
+
get "query" "options" {
|
52
|
+
output_text "query_string_options: '#{query_string_options}' path: '#{path}'"
|
53
|
+
}
|
54
|
+
"""
|
55
|
+
|
56
|
+
@request-matching @string
|
57
|
+
Scenario: Matching URI segment with strings
|
58
|
+
When I do GET request http://localhost:3000/string/hello/world
|
59
|
+
Then response status will be 200
|
60
|
+
And response content type will be text/plain
|
61
|
+
And response body will be CRLF ended lines
|
62
|
+
"""
|
63
|
+
path: 'hello/world'
|
64
|
+
"""
|
65
|
+
|
66
|
+
@request-matching @capture-any
|
67
|
+
Scenario: Capturing any URI segment
|
68
|
+
When I do GET request http://localhost:3000/any/foo/bar/hello/world
|
69
|
+
Then response status will be 200
|
70
|
+
And response content type will be text/plain
|
71
|
+
And response body will be CRLF ended lines
|
72
|
+
"""
|
73
|
+
test1: 'foo' test2: 'bar' path: 'hello/world'
|
74
|
+
"""
|
75
|
+
|
76
|
+
@request-matching @capture-any-default
|
77
|
+
Scenario: Capturing any URI segment with default value
|
78
|
+
When I do GET request http://localhost:3000/any/default/foo/bar
|
79
|
+
Then response status will be 200
|
80
|
+
And response content type will be text/plain
|
81
|
+
And response body will be CRLF ended lines
|
82
|
+
"""
|
83
|
+
test1: 'foo' test2: 'bar' test3: 'bar' test4: 'baz' path: ''
|
84
|
+
"""
|
85
|
+
|
86
|
+
@request-matching @capture-regexp
|
87
|
+
Scenario: Capturing URI segment with regexp match
|
88
|
+
When I do GET request http://localhost:3000/regexp1/abc/foobar/hello/world
|
89
|
+
Then response status will be 200
|
90
|
+
And response content type will be text/plain
|
91
|
+
And response body will be CRLF ended lines
|
92
|
+
"""
|
93
|
+
test1: 'abc' test2: 'foobar/hello/world' path: ''
|
94
|
+
"""
|
95
|
+
When I do GET request http://localhost:3000/regexp2/abc/foobar/hello/world
|
96
|
+
Then response status will be 404
|
97
|
+
|
98
|
+
@request-matching @capture-named-regexp
|
99
|
+
Scenario: Capturing URI segment with named regexp match
|
100
|
+
When I do GET request http://localhost:3000/regexp/named/ab-12/hello/world
|
101
|
+
Then response status will be 200
|
102
|
+
And response content type will be text/plain
|
103
|
+
And response body will be CRLF ended lines
|
104
|
+
"""
|
105
|
+
test1: 'ab' test2: '12' test3: 'hello/world' path: ''
|
106
|
+
"""
|
107
|
+
When I do GET request http://localhost:3000/regexp/named/nocapture/ab-12/hello/world
|
108
|
+
Then response status will be 200
|
109
|
+
And response content type will be text/plain
|
110
|
+
And response body will be CRLF ended lines
|
111
|
+
"""
|
112
|
+
path: 'hello/world'
|
113
|
+
"""
|
114
|
+
When I do GET request http://localhost:3000/regexp/named/ab-12
|
115
|
+
Then response status will be 404
|
116
|
+
When I do GET request http://localhost:3000/regexp/named/ab-123/hello/world
|
117
|
+
Then response status will be 404
|
118
|
+
When I do GET request http://localhost:3000/regexp/named/bad1/ab-12/hello/world
|
119
|
+
Then response status will be 500
|
120
|
+
When I do GET request http://localhost:3000/regexp/named/bad2/ab-12/hello/world
|
121
|
+
Then response status will be 500
|
122
|
+
And response body will be CRLF ended lines
|
123
|
+
"""
|
124
|
+
matched more arguments than named (3 for 2)
|
125
|
+
"""
|
126
|
+
|
127
|
+
@request-matching @query-key-value
|
128
|
+
Scenario: Capturing URI by presence of given key-value query string pair
|
129
|
+
When I do GET request http://localhost:3000/query/key-value/hello/world?hello=world
|
130
|
+
Then response status will be 200
|
131
|
+
And response content type will be text/plain
|
132
|
+
And response body will be CRLF ended lines
|
133
|
+
"""
|
134
|
+
query key-value matched path: 'hello/world'
|
135
|
+
"""
|
136
|
+
When I do GET request http://localhost:3000/query/key-value/hello/world?foo=bar&hello=world&bar=baz
|
137
|
+
Then response status will be 200
|
138
|
+
And response content type will be text/plain
|
139
|
+
And response body will be CRLF ended lines
|
140
|
+
"""
|
141
|
+
query key-value matched path: 'hello/world'
|
142
|
+
"""
|
143
|
+
When I do GET request http://localhost:3000/query/key-value/hello/world
|
144
|
+
Then response status will be 404
|
145
|
+
When I do GET request http://localhost:3000/query/key-value/hello/world?hello=Xorld
|
146
|
+
Then response status will be 404
|
147
|
+
When I do GET request http://localhost:3000/query/key-value/hello/world?heXlo=world
|
148
|
+
Then response status will be 404
|
149
|
+
|
150
|
+
@request-matching @query-key
|
151
|
+
Scenario: Capturing URI by query string key presence
|
152
|
+
When I do GET request http://localhost:3000/query/key/hello/world?hello=world
|
153
|
+
Then response status will be 200
|
154
|
+
And response content type will be text/plain
|
155
|
+
And response body will be CRLF ended lines
|
156
|
+
"""
|
157
|
+
key: 'world' path: 'hello/world'
|
158
|
+
"""
|
159
|
+
When I do GET request http://localhost:3000/query/key/hello/world?foo=bar&hello=foobar&bar=baz
|
160
|
+
Then response status will be 200
|
161
|
+
And response content type will be text/plain
|
162
|
+
And response body will be CRLF ended lines
|
163
|
+
"""
|
164
|
+
key: 'foobar' path: 'hello/world'
|
165
|
+
"""
|
166
|
+
When I do GET request http://localhost:3000/query/key/hello/world
|
167
|
+
Then response status will be 404
|
168
|
+
When I do GET request http://localhost:3000/query/key/hello/world?heXlo=world
|
169
|
+
Then response status will be 404
|
170
|
+
|
171
|
+
@request-matching @query-key-default
|
172
|
+
Scenario: Capturing URI by query string key presence
|
173
|
+
When I do GET request http://localhost:3000/query/key/default/hello/world?hello=world
|
174
|
+
Then response status will be 200
|
175
|
+
And response content type will be text/plain
|
176
|
+
And response body will be CRLF ended lines
|
177
|
+
"""
|
178
|
+
key: 'world' path: 'hello/world'
|
179
|
+
"""
|
180
|
+
When I do GET request http://localhost:3000/query/key/default/hello/world?foo=bar&hello=foobar&bar=baz
|
181
|
+
Then response status will be 200
|
182
|
+
And response content type will be text/plain
|
183
|
+
And response body will be CRLF ended lines
|
184
|
+
"""
|
185
|
+
key: 'foobar' path: 'hello/world'
|
186
|
+
"""
|
187
|
+
When I do GET request http://localhost:3000/query/key/default/hello/world
|
188
|
+
Then response status will be 200
|
189
|
+
And response content type will be text/plain
|
190
|
+
And response body will be CRLF ended lines
|
191
|
+
"""
|
192
|
+
key: 'abc' path: 'hello/world'
|
193
|
+
"""
|
194
|
+
When I do GET request http://localhost:3000/query/key/default/hello/world?heXlo=world
|
195
|
+
Then response status will be 200
|
196
|
+
And response content type will be text/plain
|
197
|
+
And response body will be CRLF ended lines
|
198
|
+
"""
|
199
|
+
key: 'abc' path: 'hello/world'
|
200
|
+
"""
|
201
|
+
|
202
|
+
@request-matching @query-string-options
|
203
|
+
Scenario: URI query string key-value pairs should always be available as query_string_options variable
|
204
|
+
When I do GET request http://localhost:3000/query/options/hello/world?foo=hello&bar=world
|
205
|
+
Then response status will be 200
|
206
|
+
And response content type will be text/plain
|
207
|
+
And response body will be CRLF ended lines
|
208
|
+
"""
|
209
|
+
query_string_options: 'bar:world,foo:hello' path: 'hello/world'
|
210
|
+
"""
|
211
|
+
|
@@ -10,30 +10,24 @@ Feature: Store limited original image in S3 and thumbnail based on request
|
|
10
10
|
"""
|
11
11
|
s3 key="@AWS_ACCESS_KEY_ID@" secret="@AWS_SECRET_ACCESS_KEY@" ssl=false
|
12
12
|
|
13
|
-
path "original-hash"
|
14
|
-
path "path"
|
13
|
+
path "original-hash" "#{input_digest}.#{image_mime_extension}"
|
14
|
+
path "path" "#{path}"
|
15
15
|
|
16
16
|
put "original" {
|
17
17
|
thumbnail "input" "original" operation="limit" width=100 height=100 format="jpeg" quality=95
|
18
|
-
|
19
18
|
store_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="original-hash" cache-root="/tmp"
|
20
|
-
|
21
19
|
output_store_path "original"
|
22
20
|
}
|
23
21
|
|
24
22
|
get "thumbnail" "v1" ":path" ":operation" ":width" ":height" ":options?" {
|
25
23
|
source_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="path"
|
26
|
-
|
27
24
|
thumbnail "original" "thumbnail" operation="#{operation}" width="#{width}" height="#{height}" options="#{options}" quality=84 format="png"
|
28
|
-
|
29
25
|
output_image "thumbnail" cache-control="public, max-age=31557600, s-maxage=0"
|
30
26
|
}
|
31
27
|
|
32
28
|
get "thumbnail" "v2" ":operation" ":width" ":height" {
|
33
29
|
source_s3 "original" bucket="@AWS_S3_TEST_BUCKET@" path="path" cache-root="/tmp"
|
34
|
-
|
35
30
|
thumbnail "original" "thumbnail" operation="#{operation}" width="#{width}" height="#{height}" options="#{query_string_options}" quality=84 format="png"
|
36
|
-
|
37
31
|
output_image "thumbnail" cache-control="public, max-age=31557600, s-maxage=0"
|
38
32
|
}
|
39
33
|
"""
|
@@ -85,5 +79,4 @@ Feature: Store limited original image in S3 and thumbnail based on request
|
|
85
79
|
Then response status will be 200
|
86
80
|
And response content type will be image/png
|
87
81
|
Then response body will contain PNG image of size 50x50
|
88
|
-
And that image pixel at 2x2 should be of color green
|
89
|
-
|
82
|
+
And that image pixel at 2x2 should be of color green
|