Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
9
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Open sidebar
Fabrizio Ruggeri
caravaggio
Commits
64f00532
Commit
64f00532
authored
Aug 23, 2020
by
Fabrizio Ruggeri
Browse files
Different approach to plugins.
Now the options can be passed externally if the instance is given
parent
b2510f49
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
66 additions
and
59 deletions
+66
-59
src/basePlugins/domainWhitelist.test.ts
src/basePlugins/domainWhitelist.test.ts
+10
-24
src/basePlugins/domainWhitelist.ts
src/basePlugins/domainWhitelist.ts
+3
-4
src/basePlugins/webImageLoader.ts
src/basePlugins/webImageLoader.ts
+1
-1
src/config/default.ts
src/config/default.ts
+8
-7
src/normalizers/overlay.test.ts
src/normalizers/overlay.test.ts
+1
-1
src/pipeline/index.ts
src/pipeline/index.ts
+1
-1
src/pluginLoader/pluginLoader.ts
src/pluginLoader/pluginLoader.ts
+37
-18
src/utils/imageLoader.ts
src/utils/imageLoader.ts
+5
-3
No files found.
src/basePlugins/domainWhitelist.test.ts
View file @
64f00532
...
...
@@ -17,10 +17,9 @@ const config = {} as Config;
describe
(
'
Domain Whitelist plugin
'
,
()
=>
{
describe
(
'
plugin behavior
'
,
()
=>
{
test
(
'
the factory returns a plugin
'
,
()
=>
{
const
plugin
=
domainWhitelistFactory
({
const
plugin
=
domainWhitelistFactory
({
})({
PLUGIN_IGNORE_RESULT
:
PLUGIN_IGNORE_RESULT
,
config
,
pluginOptions
:
{},
});
expect
(
plugin
).
toHaveProperty
(
'
getMiddlewares
'
);
expect
(
plugin
.
getMiddlewares
?.()).
toHaveLength
(
1
);
...
...
@@ -28,14 +27,6 @@ describe('Domain Whitelist plugin', () => {
});
describe
(
'
middleware
'
,
()
=>
{
// const plugin = domainWhitelistFactory({
// PLUGIN_IGNORE_RESULT: PLUGIN_IGNORE_RESULT,
// config,
// pluginOptions: {
// whitelist: ['caravaggio.com'],
// },
// });
// const middleware = plugin.getMiddlewares?.()[0];
const
spy
=
jest
.
fn
();
const
req
=
({
query
:
{
...
...
@@ -49,10 +40,9 @@ describe('Domain Whitelist plugin', () => {
});
test
(
'
if no whitelist is provide, next is called
'
,
()
=>
{
const
plugin
=
domainWhitelistFactory
({
const
plugin
=
domainWhitelistFactory
({
})({
PLUGIN_IGNORE_RESULT
:
PLUGIN_IGNORE_RESULT
,
config
,
pluginOptions
:
{},
});
const
middleware
=
plugin
.
getMiddlewares
?.()[
0
];
middleware
?.(
spy
)(
req
,
res
);
...
...
@@ -61,11 +51,10 @@ describe('Domain Whitelist plugin', () => {
test
(
'
if whitelist is empty, next is called
'
,
()
=>
{
const
plugin
=
domainWhitelistFactory
({
whitelist
:
[],
})({
PLUGIN_IGNORE_RESULT
:
PLUGIN_IGNORE_RESULT
,
config
,
pluginOptions
:
{
whitelist
:
[],
},
});
const
middleware
=
plugin
.
getMiddlewares
?.()[
0
];
middleware
?.(
spy
)(
req
,
res
);
...
...
@@ -74,11 +63,10 @@ describe('Domain Whitelist plugin', () => {
test
(
'
if no image is provided, next is called
'
,
()
=>
{
const
plugin
=
domainWhitelistFactory
({
whitelist
:
[
'
anything.com
'
],
})({
PLUGIN_IGNORE_RESULT
:
PLUGIN_IGNORE_RESULT
,
config
,
pluginOptions
:
{
whitelist
:
[
'
anything.com
'
],
},
});
const
middleware
=
plugin
.
getMiddlewares
?.()[
0
];
const
req
=
({
query
:
{}
}
as
unknown
)
as
ServerRequest
;
...
...
@@ -88,11 +76,10 @@ describe('Domain Whitelist plugin', () => {
test
(
'
if image is not in domain, an error is thrown
'
,
()
=>
{
const
plugin
=
domainWhitelistFactory
({
whitelist
:
[
'
anything.com
'
],
})({
PLUGIN_IGNORE_RESULT
:
PLUGIN_IGNORE_RESULT
,
config
,
pluginOptions
:
{
whitelist
:
[
'
anything.com
'
],
},
});
const
middleware
=
plugin
.
getMiddlewares
?.()[
0
];
const
req
=
({
...
...
@@ -104,11 +91,10 @@ describe('Domain Whitelist plugin', () => {
test
(
'
if image is not in a valid url, next is called
'
,
()
=>
{
const
plugin
=
domainWhitelistFactory
({
whitelist
:
[
'
anything.com
'
],
})({
PLUGIN_IGNORE_RESULT
:
PLUGIN_IGNORE_RESULT
,
config
,
pluginOptions
:
{
whitelist
:
[
'
anything.com
'
],
},
});
const
middleware
=
plugin
.
getMiddlewares
?.()[
0
];
const
req
=
({
...
...
src/basePlugins/domainWhitelist.ts
View file @
64f00532
...
...
@@ -12,10 +12,9 @@ interface DomainWhitelistOptions {
whitelist
?:
Array
<
string
>
;
}
const
domainWhitelistFactory
:
PluginConstructor
<
DomainWhitelistOptions
>
=
({
// PLUGIN_IGNORE_RESULT,
pluginOptions
,
})
=>
{
const
domainWhitelistFactory
=
(
pluginOptions
:
DomainWhitelistOptions
):
PluginConstructor
=>
()
=>
{
const
{
whitelist
=
[]
}
=
pluginOptions
||
{};
const
validDomains
=
buildRegex
(
whitelist
);
return
{
...
...
src/basePlugins/webImageLoader.ts
View file @
64f00532
import
{
PluginConstructor
}
from
'
../pluginLoader/pluginLoader
'
;
import
fetch
from
'
node-fetch
'
;
const
webImageLoaderFactory
:
PluginConstructor
<
{}
>
=
({
const
webImageLoaderFactory
=
()
:
PluginConstructor
=
>
({
PLUGIN_IGNORE_RESULT
,
})
=>
{
return
{
...
...
src/config/default.ts
View file @
64f00532
import
{
LoggerOptions
,
DestinationStream
}
from
'
pino
'
;
import
{
RawOperation
}
from
'
../utils/operationParser
'
;
import
type
{
PluginConstructor
}
from
'
../pluginLoader/pluginLoader
'
;
interface
CacheBaseConfig
{
type
:
'
memory
'
|
'
file
'
|
'
none
'
|
Function
;
...
...
@@ -151,16 +152,16 @@ export interface Config {
/**
* A series of path where to look for plugins
*/
paths
:
string
[];
paths
?
:
string
[];
/**
* All the plugins
*/
plugins
:
{
[
name
:
string
]:
{
disabled
?:
boolean
;
options
?:
unknow
n
;
}
;
};
plugins
:
Array
<
{
name
:
string
;
instance
?:
PluginConstructor
;
disabled
?:
boolea
n
;
options
?:
unknown
;
}
>
;
};
defaultOperations
?:
Array
<
RawOperation
>
;
...
...
src/normalizers/overlay.test.ts
View file @
64f00532
...
...
@@ -8,7 +8,7 @@ import pluginLoader from '../pluginLoader/pluginLoader';
import
{
ServerRequest
}
from
'
microrouter
'
;
const
mockImageGet
=
jest
.
fn
(
async
()
=>
Buffer
.
from
(
'
an image buffer
'
));
jest
.
mock
(
'
../basePlugins/webImageLoader
'
,
()
=>
(
/* config */
)
=>
({
jest
.
mock
(
'
../basePlugins/webImageLoader
'
,
()
=>
()
=>
(
/* config */
)
=>
({
inputImageLoader
:
mockImageGet
,
}));
const
config
=
{}
as
Config
;
...
...
src/pipeline/index.ts
View file @
64f00532
...
...
@@ -33,7 +33,7 @@ const pipelineCreator = (context: Context): Pipeline => {
}
=
context
;
return
async
({
url
,
rawOperations
,
req
})
=>
{
const
buffer
=
await
loader
.
get
(
url
);
const
buffer
=
await
loader
.
get
(
url
,
req
);
const
image
=
sharp
(
buffer
);
const
operations
=
normalize
([...
defaultOperations
,
...
rawOperations
]);
const
result
=
await
operations
.
reduce
(
...
...
src/pluginLoader/pluginLoader.ts
View file @
64f00532
...
...
@@ -2,13 +2,14 @@ import type { Config } from '../config/default';
import
{
tryEach
}
from
'
../utils/flow
'
;
import
webImageLoader
from
'
../basePlugins/webImageLoader
'
;
import
{
Logger
}
from
'
pino
'
;
import
{
AugmentedRequestHandler
}
from
'
microrouter
'
;
import
{
AugmentedRequestHandler
,
ServerRequest
,
options
}
from
'
microrouter
'
;
import
domainWhitelistFactory
from
'
../basePlugins/domainWhitelist
'
;
import
flatten
from
'
lodash/flatten
'
;
export
const
PLUGIN_IGNORE_RESULT
=
Symbol
(
'
PLUGIN_IGNORE_RESULT
'
);
export
interface
Plugin
{
urlTransform
?:
(
url
:
string
,
req
:
ServerRequest
)
=>
Promise
<
string
>
;
inputImageLoader
?:
(
imageUrl
:
string
)
=>
Promise
<
Buffer
|
typeof
PLUGIN_IGNORE_RESULT
|
null
>
;
...
...
@@ -17,12 +18,15 @@ export interface Plugin {
>
;
}
export
type
PluginConstructor
<
TPluginOptions
>
=
(
opt
:
{
export
type
PluginConstructor
=
(
opt
:
{
config
:
Config
;
pluginOptions
?:
TPluginOptions
;
PLUGIN_IGNORE_RESULT
:
typeof
PLUGIN_IGNORE_RESULT
;
})
=>
Plugin
;
// export type PluginConstructor<TPluginOptions = unknown> = (
// pOpt?: TPluginOptions
// ) => PluginSecondaryConstructor;
interface
PluginDescriptor
{
name
:
string
;
instance
:
Plugin
;
...
...
@@ -34,37 +38,39 @@ const pluginLoader = (config: Config, logger?: Logger): PluginManager => {
let
loadedPlugins
:
PluginDescriptor
[]
=
[
{
name
:
'
webImageLoader
'
,
instance
:
webImageLoader
({
config
,
PLUGIN_IGNORE_RESULT
}),
instance
:
webImageLoader
(
)(
{
config
,
PLUGIN_IGNORE_RESULT
}),
},
{
name
:
'
domainWhitelist
'
,
instance
:
domainWhitelistFactory
({
instance
:
domainWhitelistFactory
({
whitelist
:
config
.
whitelist
})({
config
,
PLUGIN_IGNORE_RESULT
,
pluginOptions
:
{
whitelist
:
config
.
whitelist
},
}),
},
];
if
(
config
.
plugins
)
{
const
{
paths
,
plugins
=
{}
}
=
config
.
plugins
;
loadedPlugins
=
Object
.
entries
(
plugins
)
.
filter
(([,
{
disabled
}])
=>
!
disabled
)
.
reduce
<
PluginDescriptor
[]
>
((
acc
,
opt
)
=>
{
const
[
name
,
{
options
}]
=
opt
;
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
plugin
=
require
(
require
.
resolve
(
name
,
{
paths
,
}))
as
PluginConstructor
<
unknown
>
;
const
{
paths
,
plugins
=
[]
}
=
config
.
plugins
;
loadedPlugins
=
plugins
.
filter
((
plugin
)
=>
!
plugin
.
disabled
)
.
reduce
<
PluginDescriptor
[]
>
((
acc
,
{
name
,
instance
,
options
})
=>
{
let
plugin
:
PluginConstructor
;
if
(
instance
)
{
plugin
=
instance
;
}
else
{
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
loaded
=
require
(
require
.
resolve
(
name
,
{
paths
,
}));
plugin
=
loaded
(
options
);
}
return
[
...
acc
,
{
name
,
instance
:
plugin
({
config
,
pluginOptions
:
options
,
PLUGIN_IGNORE_RESULT
,
}),
},
...
...
@@ -83,6 +89,19 @@ const pluginLoader = (config: Config, logger?: Logger): PluginManager => {
};
return
{
urlTransform
:
async
(
url
,
req
)
=>
{
const
fns
=
getFnsFromPlugins
(
'
urlTransform
'
);
if
(
fns
.
length
===
0
)
return
url
;
try
{
const
result
=
await
tryEach
(
fns
,
{
onError
:
onPluginError
,
ignoreResult
:
(
r
)
=>
r
===
PLUGIN_IGNORE_RESULT
,
})(
url
,
req
);
return
result
||
url
;
}
catch
(
e
)
{
return
url
;
}
},
inputImageLoader
:
async
(
imageUrl
)
=>
{
const
fns
=
getFnsFromPlugins
(
'
inputImageLoader
'
);
try
{
...
...
@@ -93,7 +112,7 @@ const pluginLoader = (config: Config, logger?: Logger): PluginManager => {
return
result
;
}
catch
(
e
)
{
throw
new
Error
(
'
[PLUGIN:inputImageLoader] failed. No plugin is able to
handle this operation
'
`
[PLUGIN:inputImageLoader] failed. No plugin is able to
download "
${
imageUrl
}
"`
);
}
},
...
...
src/utils/imageLoader.ts
View file @
64f00532
import
{
Context
}
from
'
..
'
;
import
cache
from
'
../caches/cache
'
;
import
{
CacheConfig
}
from
'
../config/default
'
;
import
{
ServerRequest
}
from
'
microrouter
'
;
const
defaultInputCache
:
CacheConfig
=
{
type
:
'
none
'
,
...
...
@@ -12,14 +13,14 @@ interface ImageLoader {
* Given an url, returns the loaded image or raises an error
* @throws Error if cannot load the image
*/
get
:
(
url
:
string
)
=>
Promise
<
Buffer
>
;
get
:
(
url
:
string
,
req
:
ServerRequest
)
=>
Promise
<
Buffer
>
;
}
const
imageLoader
=
(
context
:
Context
):
ImageLoader
=>
{
const
{
logger
}
=
context
;
const
inputCache
=
cache
(
context
.
config
.
caches
?.
input
||
defaultInputCache
);
return
{
get
:
async
(
url
)
=>
{
get
:
async
(
url
,
req
)
=>
{
const
cached
=
await
inputCache
.
get
(
url
);
if
(
cached
)
{
logger
.
debug
(
...
...
@@ -27,8 +28,9 @@ const imageLoader = (context: Context): ImageLoader => {
);
return
cached
.
data
;
}
const
finalUrl
=
await
context
.
pluginManager
.
urlTransform
(
url
,
req
);
const
loaded
=
(
await
context
.
pluginManager
.
inputImageLoader
(
u
rl
finalU
rl
))
as
Buffer
|
null
;
if
(
loaded
===
null
)
{
throw
new
Error
(
`Cannot load image "
${
url
}
"`
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment