Skip to content

Commit 46ad550

Browse files
committed
Refactor old settings module and module hierarchy in general
1 parent 00cd1b9 commit 46ad550

File tree

11 files changed

+143
-199
lines changed

11 files changed

+143
-199
lines changed

config/test.exs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +0,0 @@
1-
import Config
2-
3-
config :iiif_image_plug,
4-
max_width: 600,
5-
max_height: 400,
6-
max_area: 600 * 400

lib/iiif_image_plug/v3.ex

Lines changed: 34 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -3,93 +3,19 @@ defmodule IIIFImagePlug.V3 do
33

44
alias Vix.Vips.Image
55

6-
alias IIIFImagePlug.V3.Data
6+
alias IIIFImagePlug.V3.{
7+
Options,
8+
Data
9+
}
710

811
import Plug.Conn
912

1013
require Logger
1114

1215
@moduledoc """
13-
This plug implements the IIIF Image API version 3 (see also https://iiif.io/api/image/3.0/).
14-
15-
## Options
16-
17-
### `:identifier_to_path_callback` required
18-
An arity 1 callback function that resolves a given IIIF identifier to a file path (string).
19-
20-
### `:max_width` (default: `10000`)
21-
The maximum image width the plug will serve.
22-
23-
### `:max_height` (default: `10000`)
24-
The maximum image height the plug will serve.
25-
26-
### `:max_area` (default: `100000000`)
27-
The maximum amount of image pixels the plug will serve (does not necessarily have to be `max_width` * `max_height`).
28-
29-
### `:preferred_formats` (default: `[:jpg]`)
30-
The [preferred formats](https://iiif.io/api/image/3.0/#55-preferred-formats) to be used for your service.
31-
32-
### `:extra_formats` (default: `[:png, :webp, :tif]`)
33-
The [extra formats](https://iiif.io/api/image/3.0/#57-extra-functionality) your service can deliver.
34-
35-
### `:temp_dir` (default: Evaluates [System.tmp_dir!()](https://hexdocs.pm/elixir/System.html#tmp_dir!/0) and creates
36-
a directory "iiif_image_plug" there.
37-
38-
Because of how the TIF file format is structured, the plug can not stream the image if tif was requested as the response
39-
[format](https://iiif.io/api/image/3.0/#45-format). Instead, the image gets first written to a temporary file, which is then streamed
40-
from disk and finally getting deleted.
41-
42-
If you want to forgo this file creation, you can set this option to `:buffer` instead of a file path. This will configure
43-
the plug to write the complete image to memory instead of disk - which is faster but also may cause memory issues if
44-
very large images are requested.
45-
46-
### `:scheme` (optional)
47-
Callback function to override the scheme evaluated from the `%Plug.Conn{}`, useful if your Elixir app runs behind a proxy.
48-
49-
### `:host` (optional)
50-
Callback function to override the host evaluated from the `%Plug.Conn{}`, useful if your Elixir app runs behind a proxy.
51-
52-
### `:port` (optional)
53-
Callback function to override the port evaluated from the `%Plug.Conn{}`, useful if your Elixir app runs behind a proxy.
54-
55-
### `:identifier_to_rights_callback` (optional)
56-
An arity 1 callback function that returns a [rights](https://iiif.io/api/image/3.0/#56-rights) statement for a given identifier.
57-
58-
### `:identifier_to_part_of_callback` (optional)
59-
An arity 1 callback function that returns a list of [part of](https://iiif.io/api/image/3.0/#58-linking-properties) properties for a given identifier.
60-
61-
### `:identifier_to_see_also_callback` (optional)
62-
An arity 1 callback function that returns a list of [see also](https://iiif.io/api/image/3.0/#58-linking-properties) properties for a given identifier.
63-
64-
### `:identifier_to_service_callback` (optional)
65-
An arity 1 callback function that returns a list of [service](https://iiif.io/api/image/3.0/#58-linking-properties) properties for a given identifier.
66-
67-
### `:status_callbacks` (optional)
68-
A map where each key is a HTTP status code (integer), and each value an arity 2 callback that can be used to replace the plug's default response. Each
69-
callback should accept a plug as its first parameter and a Map (containing the error message) as its second parameter.
16+
This plug implements the IIIF Image API version 3 (see also https://iiif.io/api/image/3.0).
7017
"""
7118

72-
defmodule Settings do
73-
@moduledoc false
74-
75-
@enforce_keys [
76-
:max_width,
77-
:max_height,
78-
:max_area,
79-
:preferred_formats,
80-
:extra_formats,
81-
:temp_dir
82-
]
83-
defstruct [
84-
:max_width,
85-
:max_height,
86-
:max_area,
87-
:preferred_formats,
88-
:extra_formats,
89-
:temp_dir
90-
]
91-
end
92-
9319
@callback identifier_to_path(identifier :: String.t()) ::
9420
{:ok, String.t()} | {:error, atom()}
9521
@callback scheme() :: String.t() | nil
@@ -102,14 +28,11 @@ defmodule IIIFImagePlug.V3 do
10228
@callback send_error(
10329
conn :: Conn.t(),
10430
status_code :: number(),
105-
error_code :: atom(),
106-
error_msg :: String.t()
31+
error_code :: atom()
10732
) :: Conn.t()
10833

10934
defmacro __using__(_opts) do
110-
#### do something with opts
11135
quote do
112-
#### return some code to inject in the caller
11336
import Plug.Conn
11437

11538
@behaviour Plug
@@ -137,8 +60,8 @@ defmodule IIIFImagePlug.V3 do
13760
# replace the default. Because we want to give the users the opportunity to customize only specific
13861
# errors, the @before_compile below will re-add our defaults as a fallback.
13962

140-
def send_error(%Conn{} = conn, status_code, error_type, error_msg) do
141-
IIIFImagePlug.V3.send_error(conn, status_code, error_type, error_msg)
63+
def send_error(%Conn{} = conn, status_code, error_type) do
64+
IIIFImagePlug.V3.send_error(conn, status_code, error_type)
14265
end
14366

14467
@before_compile {IIIFImagePlug.V3, :add_send_error_fallback}
@@ -150,43 +73,27 @@ defmodule IIIFImagePlug.V3 do
15073
part_of: 1,
15174
see_also: 1,
15275
service: 1,
153-
send_error: 4
76+
send_error: 3
15477
end
15578
end
15679

15780
defmacro add_send_error_fallback(_env) do
15881
quote do
159-
def send_error(%Conn{} = conn, status_code, error_type, error_msg) do
160-
IIIFImagePlug.V3.send_error(conn, status_code, error_type, error_msg)
82+
def send_error(%Conn{} = conn, status_code, error_type) do
83+
IIIFImagePlug.V3.send_error(conn, status_code, error_type)
16184
end
16285
end
16386
end
16487

165-
@default_preferred_format [:jpg]
166-
@default_extra_formats [:webp, :png, :tif]
167-
168-
@default_max_width Application.compile_env(:iiif_image_plug, :max_width, 10000)
169-
@default_max_height Application.compile_env(:iiif_image_plug, :max_height, 10000)
170-
@default_max_area Application.compile_env(:iiif_image_plug, :max_area, 10000 * 10000)
171-
172-
def init(opts) when is_map(opts) do
173-
temp_dir = opts[:temp_dir] || Path.join(System.tmp_dir!(), "iiif_image_plug")
174-
88+
def init(%Options{temp_dir: temp_dir} = opts) do
17589
if temp_dir != :buffer do
17690
File.mkdir_p!(temp_dir)
17791
end
17892

179-
%Settings{
180-
max_width: opts[:max_width] || @default_max_width,
181-
max_height: opts[:max_height] || @default_max_height,
182-
max_area: opts[:max_area] || @default_max_area,
183-
temp_dir: temp_dir,
184-
preferred_formats: opts[:preferred_formats] || @default_preferred_format,
185-
extra_formats: opts[:extra_formats] || @default_extra_formats
186-
}
93+
opts
18794
end
18895

189-
def call(%Plug.Conn{path_info: [identifier]} = conn, _settings, module) do
96+
def call(%Plug.Conn{path_info: [identifier]} = conn, _options, module) do
19097
conn
19198
|> resp(:found, "")
19299
|> put_resp_header(
@@ -197,10 +104,10 @@ defmodule IIIFImagePlug.V3 do
197104

198105
def call(
199106
%Plug.Conn{path_info: [identifier, "info.json"]} = conn,
200-
settings,
107+
options,
201108
module
202109
) do
203-
case generate_image_info(conn, identifier, settings, module) do
110+
case generate_image_info(conn, identifier, options, module) do
204111
{:ok, info} ->
205112
conn
206113
|> put_resp_content_type("application/ld+json")
@@ -210,8 +117,7 @@ defmodule IIIFImagePlug.V3 do
210117
module.send_error(
211118
conn,
212119
404,
213-
:no_file,
214-
nil
120+
:no_file
215121
)
216122

217123
{:error, :no_image_file} ->
@@ -220,8 +126,7 @@ defmodule IIIFImagePlug.V3 do
220126
module.send_error(
221127
conn,
222128
500,
223-
:internal_error,
224-
nil
129+
:internal_error
225130
)
226131
end
227132
end
@@ -230,10 +135,10 @@ defmodule IIIFImagePlug.V3 do
230135
%Plug.Conn{
231136
path_info: [identifier, region, size, rotation, quality_and_format]
232137
} = conn,
233-
%Settings{
138+
%Options{
234139
temp_dir: temp_dir
235140
} =
236-
settings,
141+
options,
237142
module
238143
) do
239144
case Data.get(
@@ -242,7 +147,7 @@ defmodule IIIFImagePlug.V3 do
242147
URI.decode(size),
243148
URI.decode(rotation),
244149
quality_and_format,
245-
settings,
150+
options,
246151
module
247152
) do
248153
{%Image{} = image, format} ->
@@ -266,8 +171,7 @@ defmodule IIIFImagePlug.V3 do
266171
module.send_error(
267172
conn,
268173
404,
269-
:no_file,
270-
nil
174+
:no_file
271175
)
272176

273177
{:error, :no_image_file} ->
@@ -276,30 +180,27 @@ defmodule IIIFImagePlug.V3 do
276180
module.send_error(
277181
conn,
278182
500,
279-
:internal_error,
280-
nil
183+
:internal_error
281184
)
282185

283186
{:error, type} ->
284187
module.send_error(
285188
conn,
286189
400,
287-
type,
288-
nil
190+
type
289191
)
290192
end
291193
end
292194

293195
def call(
294196
conn,
295-
_settings,
197+
_options,
296198
module
297199
) do
298200
module.send_error(
299201
conn,
300202
404,
301-
:unknown_route,
302-
nil
203+
:unknown_route
303204
)
304205
end
305206

@@ -337,22 +238,12 @@ defmodule IIIFImagePlug.V3 do
337238
end)
338239
end
339240

340-
def send_error(conn, status_code, error_type, error_msg) do
341-
body =
342-
%{error: error_type}
343-
344-
body =
345-
if error_msg do
346-
Map.put(body, :error_msg, error_msg)
347-
else
348-
body
349-
end
350-
241+
def send_error(conn, status_code, error_type) do
351242
conn
352243
|> put_resp_content_type("application/json")
353244
|> send_resp(
354245
status_code,
355-
Jason.encode!(body)
246+
Jason.encode!(%{error: error_type})
356247
)
357248
end
358249

@@ -381,7 +272,7 @@ defmodule IIIFImagePlug.V3 do
381272
def host(), do: nil
382273
def port(), do: nil
383274

384-
def generate_image_info(conn, identifier, settings, module) do
275+
def generate_image_info(conn, identifier, options, module) do
385276
with {:identifier, {:ok, path}} <- {:identifier, module.identifier_to_path(identifier)},
386277
{:file_exists, true} <- {:file_exists, File.exists?(path)},
387278
{:file_opened, {:ok, file}} <- {:file_opened, Image.new_from_file(path)} do
@@ -395,9 +286,9 @@ defmodule IIIFImagePlug.V3 do
395286
width: Image.width(file),
396287
height: Image.height(file),
397288
profile: "level2",
398-
maxHeight: settings.max_height,
399-
maxWidth: settings.max_width,
400-
maxArea: settings.max_area,
289+
maxHeight: options.max_height,
290+
maxWidth: options.max_width,
291+
maxArea: options.max_area,
401292
extra_features: [
402293
"mirroring",
403294
"regionByPct",
@@ -411,8 +302,8 @@ defmodule IIIFImagePlug.V3 do
411302
"sizeByWh",
412303
"sizeUpscaling"
413304
],
414-
preferredFormat: settings.preferred_formats,
415-
extraFormats: settings.extra_formats,
305+
preferredFormat: options.preferred_formats,
306+
extraFormats: options.extra_formats,
416307
extraQualities: [:color, :gray, :bitonal]
417308
}
418309
|> maybe_add_rights(identifier, module)

lib/iiif_image_plug/v3/data.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ defmodule IIIFImagePlug.V3.Data do
22
alias Vix.Vips.Operation
33
alias Vix.Vips.Image
44

5-
alias IIIFImagePlug.V3.Size.Scaling
6-
alias IIIFImagePlug.V3.Region.ExtractArea
7-
alias IIIFImagePlug.V3.Quality
8-
alias IIIFImagePlug.V3.Rotation
9-
alias IIIFImagePlug.V3.Size
10-
alias IIIFImagePlug.V3.Region
5+
alias IIIFImagePlug.V3.Data.Size.Scaling
6+
alias IIIFImagePlug.V3.Data.Region.ExtractArea
7+
alias IIIFImagePlug.V3.Data.Quality
8+
alias IIIFImagePlug.V3.Data.Rotation
9+
alias IIIFImagePlug.V3.Data.Size
10+
alias IIIFImagePlug.V3.Data.Region
1111

1212
@moduledoc """
1313
Produces image data based on the given IIIF parameters and Plug settings.

lib/iiif_image_plug/v3/quality.ex renamed to lib/iiif_image_plug/v3/data/quality.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
defmodule IIIFImagePlug.V3.Quality do
1+
defmodule IIIFImagePlug.V3.Data.Quality do
22
@moduledoc false
33

44
alias Vix.Vips.{
55
Operation,
66
Image
77
}
88

9-
alias IIIFImagePlug.V3.Settings
9+
alias IIIFImagePlug.V3.Options
1010

11-
def parse(quality_and_format, %Settings{
11+
def parse(quality_and_format, %Options{
1212
preferred_formats: preferred_formats,
1313
extra_formats: extra_formats
1414
})
@@ -26,7 +26,7 @@ defmodule IIIFImagePlug.V3.Quality do
2626
end
2727

2828
_ ->
29-
:error
29+
{:error, :invalid_quality_and_format}
3030
end
3131
end
3232

lib/iiif_image_plug/v3/region.ex renamed to lib/iiif_image_plug/v3/data/region.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule IIIFImagePlug.V3.Region do
1+
defmodule IIIFImagePlug.V3.Data.Region do
22
@moduledoc false
33
defmodule ExtractArea do
44
@moduledoc false

lib/iiif_image_plug/v3/rotation.ex renamed to lib/iiif_image_plug/v3/data/rotation.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule IIIFImagePlug.V3.Rotation do
1+
defmodule IIIFImagePlug.V3.Data.Rotation do
22
@moduledoc false
33
alias Vix.Vips.{
44
Operation,

0 commit comments

Comments
 (0)