-
Notifications
You must be signed in to change notification settings - Fork 0
/
delegates.rb
404 lines (384 loc) · 15.5 KB
/
delegates.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
##
# Sample Ruby delegate script containing stubs and documentation for all
# available delegate methods. See the user manual for more information.
#
# The application will create an instance of this class early in the request
# cycle and dispose of it at the end of the request cycle. Instances don't need
# to be thread-safe, but sharing information across instances (requests)
# **does** need to be done thread-safely.
#
# This version of the script works with Cantaloupe version >= 5.
#
class CustomDelegate
##
# Attribute for the request context, which is a hash containing information
# about the current request.
#
# This attribute will be set by the server before any other methods are
# called. Methods can access its keys like:
#
# ```
# identifier = context['identifier']
# ```
#
# The hash will contain the following keys in response to all requests:
#
# * `client_ip` [String] Client IP address.
# * `cookies` [Hash<String,String>] Hash of cookie name-value pairs.
# * `full_size` [Hash<String,Integer>] Hash with `width` and `height`
# keys corresponding to the pixel dimensions of the
# source image.
# * `identifier` [String] Image identifier.
# * `local_uri` [String] URI seen by the application, which may be
# different from `request_uri` when operating behind a
# reverse-proxy server.
# * `metadata` [Hash<String,Object>] Embedded image metadata. Object
# structure varies depending on the source image.
# See the `metadata()` method.
# * `page_count` [Integer] Page count.
# * `page_number` [Integer] Page number.
# * `request_headers` [Hash<String,String>] Hash of header name-value pairs.
# * `request_uri` [String] URI requested by the client.
# * `scale_constraint` [Array<Integer>] Two-element array with scale
# constraint numerator at position 0 and denominator at
# position 1.
#
# It will contain the following additional string keys in response to image
# requests, after the image has been accessed:
#
# * `operations` [Array<Hash<String,Object>>] Array of operations in
# order of application. Only operations that are not
# no-ops will be included. Every hash contains a `class`
# key corresponding to the operation class name, which
# will be one of the `e.i.l.c.operation.Operation`
# implementations.
# * `output_format` [String] Output format media (MIME) type.
# * `resulting_size` [Hash<String,Integer>] Hash with `width` and `height`
# keys corresponding to the pixel dimensions of the
# resulting image after all operations have been applied.
#
# @return [Hash] Request context.
#
attr_accessor :context
##
# Deserializes the given meta-identifier string into a hash of its component
# parts.
#
# This method is used only when the `meta_identifier.transformer`
# configuration key is set to `DelegateMetaIdentifierTransformer`.
#
# The hash contains the following keys:
#
# * `identifier` [String] Required.
# * `page_number` [Integer] Optional.
# * `scale_constraint` [Array<Integer>] Two-element array with scale
# constraint numerator at position 0 and denominator at
# position 1. Optional.
#
# @param meta_identifier [String]
# @return Hash<String,Object> See above. The return value should be
# compatible with the argument to
# {serialize_meta_identifier}.
#
def deserialize_meta_identifier(meta_identifier)
end
##
# Serializes the given meta-identifier hash.
#
# This method is used only when the `meta_identifier.transformer`
# configuration key is set to `DelegateMetaIdentifierTransformer`.
#
# See {deserialize_meta_identifier} for a description of the hash structure.
#
# @param components [Hash<String,Object>]
# @return [String] Serialized meta-identifier compatible with the argument to
# {deserialize_meta_identifier}.
#
def serialize_meta_identifier(components)
end
##
# Returns authorization status for the current request. This method is called
# upon all requests to all public endpoints early in the request cycle,
# before the image has been accessed. This means that some context keys (like
# `full_size`) will not be available yet.
#
# This method should implement all possible authorization logic except that
# which requires any of the context keys that aren't yet available. This will
# ensure efficient authorization failures.
#
# Implementations should assume that the underlying resource is available,
# and not try to check for it.
#
# Possible return values:
#
# 1. Boolean true/false, indicating whether the request is fully authorized
# or not. If false, the client will receive a 403 Forbidden response.
# 2. Hash with a `status_code` key.
# a. If it corresponds to an integer from 200-299, the request is
# authorized.
# b. If it corresponds to an integer from 300-399:
# i. If the hash also contains a `location` key corresponding to a
# URI string, the request will be redirected to that URI using
# that code.
# ii. If the hash also contains `scale_numerator` and
# `scale_denominator` keys, the request will be
# redirected using that code to a virtual reduced-scale version of
# the source image.
# c. If it corresponds to 401, the hash must include a `challenge` key
# corresponding to a WWW-Authenticate header value.
#
# @param options [Hash] Empty hash.
# @return [Boolean,Hash<String,Object>] See above.
#
def pre_authorize(options = {})
true
end
##
# Returns authorization status for the current request. Will be called upon
# all requests to all public image (not information) endpoints.
#
# This is a counterpart of `pre_authorize()` that is invoked later in the
# request cycle, once more information about the underlying image has become
# available. It should only contain logic that depends on context keys that
# contain information about the source image (like `full_size`, `metadata`,
# etc.)
#
# Implementations should assume that the underlying resource is available,
# and not try to check for it.
#
# @param options [Hash] Empty hash.
# @return [Boolean,Hash<String,Object>] See the documentation of
# `pre_authorize()`.
#
def authorize(options = {})
true
end
##
# Adds additional keys to an Image API 2.x information response. See the
# [IIIF Image API 2.1](http://iiif.io/api/image/2.1/#image-information)
# specification and "endpoints" section of the user manual.
#
# @param options [Hash] Empty hash.
# @return [Hash] Hash to merge into an Image API 2.x information response.
# Return an empty hash to add nothing.
#
def extra_iiif2_information_response_keys(options = {})
{}
end
##
# Adds additional keys to an Image API 3.x information response. See the
# [IIIF Image API 3.0](http://iiif.io/api/image/3.0/#image-information)
# specification and "endpoints" section of the user manual.
#
# @param options [Hash] Empty hash.
# @return [Hash] Hash to merge into an Image API 3.x information response.
# Return an empty hash to add nothing.
#
def extra_iiif3_information_response_keys(options = {})
{}
end
##
# Tells the server which source to use for the given identifier.
#
# @param options [Hash] Empty hash.
# @return [String] Source name.
#
def source(options = {})
if context['identifier'].include? 'http://' or context['identifier'].include? 'https://'
str = "HttpSource"
else
str = "FilesystemSource"
end
return str
end
##
# N.B.: this method should not try to perform authorization. `authorize()`
# should be used instead.
#
# @param options [Hash] Empty hash.
# @return [String,nil] Blob key of the image corresponding to the given
# identifier, or nil if not found.
#
def azurestoragesource_blob_key(options = {})
end
##
# N.B.: this method should not try to perform authorization. `authorize()`
# should be used instead.
#
# @param options [Hash] Empty hash.
# @return [String,nil] Absolute pathname of the image corresponding to the
# given identifier, or nil if not found.
#
def filesystemsource_pathname(options = {})
filepath = "{path to resource folder}/" # add trailing slash
if context['identifier'].include? '__'
parts = context['identifier'].split('__')
filepath = filepath.concat(parts[0]).concat("/").concat(parts[1])
else
filepath = filepath.concat(context['identifier'])
end
puts "filesystemsource_pathname returning pathname: ".concat(filepath)
return filepath;
end
##
# Returns one of the following:
#
# 1. String URI
# 2. Hash with the following keys:
# * `uri` [String] (required)
# * `username` [String] For HTTP Basic authentication (optional).
# * `secret` [String] For HTTP Basic authentication (optional).
# * `headers` [Hash<String,String>] Hash of request headers (optional).
# 3. nil if not found.
#
# N.B.: this method should not try to perform authorization. `authorize()`
# should be used instead.
#
# @param options [Hash] Empty hash.
# @return See above.
#
def httpsource_resource_info(options = {})
end
##
# N.B.: this method should not try to perform authorization. `authorize()`
# should be used instead.
#
# @param options [Hash] Empty hash.
# @return [String] Identifier of the image corresponding to the given
# identifier in the database.
#
def jdbcsource_database_identifier(options = {})
end
##
# Returns either the media (MIME) type of an image, or an SQL statement that
# can be used to retrieve it, if it is stored in the database. In the latter
# case, the "SELECT" and "FROM" clauses should be in uppercase in order to
# be autodetected. If nil is returned, the media type will be inferred some
# other way, such as by identifier extension or magic bytes.
#
# @param options [Hash] Empty hash.
# @return [String, nil]
#
def jdbcsource_media_type(options = {})
end
##
# @param options [Hash] Empty hash.
# @return [String] SQL statement that selects the BLOB corresponding to the
# value returned by `jdbcsource_database_identifier()`.
#
def jdbcsource_lookup_sql(options = {})
end
##
# N.B.: this method should not try to perform authorization. `authorize()`
# should be used instead.
#
# @param options [Hash] Empty hash.
# @return [Hash<String,Object>,nil] Hash containing `bucket` and `key` keys;
# or nil if not found.
#
def s3source_object_info(options = {})
end
##
# Tells the server what overlay, if any, to apply to an image. Called upon
# all image requests to any endpoint if overlays are enabled and the overlay
# strategy is set to `ScriptStrategy` in the application configuration.
#
# Return values:
#
# 1. For string overlays, a hash with the following keys:
# * `background_color` [String] CSS-compliant RGA(A) color.
# * `color` [String] CSS-compliant RGA(A) color.
# * `font` [String] Font name. Launch with the -list-fonts
# argument to see a list of available fonts.
# * `font_min_size` [Integer] Minimum font size in points (ignored
# when `word_wrap` is true).
# * `font_size` [Integer] Font size in points.
# * `font_weight` [Float] Font weight based on 1.
# * `glyph_spacing` [Float] Glyph spacing based on 0.
# * `inset` [Integer] Pixels of inset.
# * `position` [String] Position like `top left`, `center right`,
# etc.
# * `string` [String] String to draw.
# * `stroke_color` [String] CSS-compliant RGB(A) text outline color.
# * `stroke_width` [Float] Text outline width in pixels.
# * `word_wrap` [Boolean] Whether to wrap long lines within
# `string`.
# 2. For image overlays, a hash with the following keys:
# * `image` [String] Image pathname or URL.
# * `position` [String] See above.
# * `inset` [Integer] See above.
# 3. nil for no overlay.
#
# @param options [Hash] Empty hash.
# @return See above.
#
def overlay(options = {})
end
##
# Tells the server what regions of an image to redact in response to a
# particular request. Will be called upon all image requests to any endpoint.
#
# @param options [Hash] Empty hash.
# @return [Array<Hash<String,Integer>>] Array of hashes, each with `x`, `y`,
# `width`, and `height` keys; or an empty array if no redactions are
# to be applied.
#
def redactions(options = {})
[]
end
##
# Returns XMP metadata to embed in the derivative image.
#
# Source image metadata is available in the `metadata` context key, and has
# the following structure:
#
# ```
# {
# "exif": {
# "tagSet": "Baseline TIFF",
# "fields": {
# "Field1Name": value,
# "Field2Name": value,
# "EXIFIFD": {
# "tagSet": "EXIF",
# "fields": {
# "Field1Name": value,
# "Field2Name": value
# }
# }
# }
# },
# "iptc": [
# "Field1Name": value,
# "Field2Name": value
# ],
# "xmp_string": "<rdf:RDF>...</rdf:RDF>",
# "xmp_model": https://jena.apache.org/documentation/javadoc/jena/org/apache/jena/rdf/model/Model.html
# "native": {
# # structure varies
# }
# }
# ```
#
# * The `exif` key refers to embedded EXIF data. This also includes IFD0
# metadata from source TIFFs, whether or not an EXIF IFD is present.
# * The `iptc` key refers to embedded IPTC IIM data.
# * The `xmp_string` key refers to raw embedded XMP data, which may or may
# not contain EXIF and/or IPTC information.
# * The `xmp_model` key contains a Jena Model object pre-loaded with the
# contents of `xmp_string`.
# * The `native` key refers to format-specific metadata.
#
# Any combination of the above keys may be present or missing depending on
# what is available in a particular source image.
#
# Only XMP can be embedded in derivative images. See the user manual for
# examples of working with the XMP model programmatically.
#
# @return [String,Model,nil] String or Jena model containing XMP data to
# embed in the derivative image, or nil to not
# embed anything.
#
def metadata(options = {})
end
end