Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
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
dc5cb26b
Commit
dc5cb26b
authored
Aug 09, 2020
by
Fabrizio Ruggeri
Browse files
Can work under a subfolder
parent
987a39e9
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
49 additions
and
30 deletions
+49
-30
src/config/default.ts
src/config/default.ts
+11
-7
src/errors/BadRequestError.ts
src/errors/BadRequestError.ts
+1
-1
src/errors/CError.ts
src/errors/CError.ts
+2
-2
src/errors/UnknownOperationError.ts
src/errors/UnknownOperationError.ts
+1
-1
src/logger.ts
src/logger.ts
+4
-1
src/middlewares/errorHandler.ts
src/middlewares/errorHandler.ts
+6
-13
src/routes/index.ts
src/routes/index.ts
+13
-2
src/utils/imageLoader.ts
src/utils/imageLoader.ts
+7
-1
src/utils/misc.ts
src/utils/misc.ts
+4
-2
No files found.
src/config/default.ts
View file @
dc5cb26b
...
...
@@ -71,24 +71,28 @@ export type CacheOptions =
|
NoneCacheOptions
;
export
interface
Config
{
/**
* Set this value if caravaggio is served from a subfolder. i.e "/api"
*/
basePath
?:
string
;
/**
* Caravaggio has several caches
*/
caches
:
{
caches
?
:
{
/**
* OUTPUT CACHE
* Cache for the transformed images.
* Given the same input url and the same transformation options,
* this cache saves the output buffer to avoir re-compute the transformations
*/
output
:
CacheConfig
;
output
?
:
CacheConfig
;
/**
* INPUT CACHE
* This cache let you avoid download several time the same input image
* Given the same url, the original image is cached and not re-downloaded
* This accept the same type as the output cache
*/
input
:
CacheConfig
;
input
?
:
CacheConfig
;
};
/**
* Define the cache directive sent in the response
...
...
@@ -113,7 +117,7 @@ export interface Config {
/**
* Logger definition. Define how the application should log event
*/
logger
:
{
logger
?
:
{
/**
* level: The log level. One among: fatal, error, warn, info, debug, trace, silent
* The log will appear from your choosen level and upon, i.e.
...
...
@@ -121,11 +125,11 @@ export interface Config {
* (info -> info, warn, error, fatal)
* pretty: Print a pretty out instead of the json one
*/
options
:
LoggerOptions
;
options
?
:
LoggerOptions
;
/**
* destination: Where to stream the log. Can be `stdout`, `stderr` or a file path
* destination: Where to stream the log. Can be `
process.
stdout`, `
process.
stderr` or a file path
*/
destination
:
DestinationStream
;
destination
?
:
DestinationStream
;
};
/**
* Let you decide how to show errors.
...
...
src/errors/BadRequestError.ts
View file @
dc5cb26b
import
CError
from
'
./CError
'
;
class
BadRequestError
extends
CError
{
constructor
(
message
:
string
,
docUri
:
string
)
{
constructor
(
message
:
string
,
docUri
:
string
|
null
)
{
super
(
message
||
'
Bad request error
'
,
docUri
,
400
);
}
}
...
...
src/errors/CError.ts
View file @
dc5cb26b
class
CError
extends
Error
{
public
statusCode
:
number
;
public
docUri
:
string
;
public
docUri
:
string
|
null
=
null
;
constructor
(
message
:
string
,
docUri
:
string
,
statusCode
=
500
)
{
constructor
(
message
:
string
,
docUri
:
string
|
null
,
statusCode
=
500
)
{
super
(
message
);
this
.
statusCode
=
statusCode
;
this
.
docUri
=
docUri
;
...
...
src/errors/UnknownOperationError.ts
View file @
dc5cb26b
...
...
@@ -2,6 +2,6 @@ import BadRequestError from './BadRequestError';
export
default
class
UnknownOperationError
extends
BadRequestError
{
constructor
(
operation
:
string
)
{
super
(
`Unknown operation "
${
operation
}
"`
,
'
docs.html
'
);
super
(
`Unknown operation "
${
operation
}
"`
,
null
);
}
}
src/logger.ts
View file @
dc5cb26b
...
...
@@ -6,7 +6,10 @@ let logger: pino.Logger;
const
createLogger
=
(
config
:
Config
)
=>
{
if
(
logger
)
return
logger
;
const
{
logger
:
{
options
,
destination
},
logger
:
{
options
=
{},
destination
=
process
.
stdout
}
=
{
destination
:
process
.
stdout
,
options
:
{},
},
}
=
config
;
logger
=
pino
(
options
,
destination
);
...
...
src/middlewares/errorHandler.ts
View file @
dc5cb26b
...
...
@@ -67,13 +67,10 @@ const buildHtmlError: ErrorBuilder = (err, res) => {
<div>
<h1>Error</h1>
<p>
${
err
.
message
||
UNKNOWN_ERROR_MESSAGE
}
${
err
.
docUri
!==
null
?
`<br />See <a target="_blank" href="
${
buildDocumentationLink
(
err
.
docUri
)}
">
${
buildDocumentationLink
(
err
.
docUri
)}
</a>`
:
''
}
</p>
<br />See <a target="_blank" href="
${
buildDocumentationLink
(
err
.
docUri
)}
">
${
buildDocumentationLink
(
err
.
docUri
)}
</a>
</p>
</div>
</div>
</div>
...
...
@@ -95,12 +92,8 @@ const buildJsonError: ErrorBuilder = (err, res) => {
const
buildErrorText
:
ErrorBuilder
=
(
err
,
res
)
=>
{
res
.
setHeader
(
'
Content-Type
'
,
'
text/plain; charset=UTF-8
'
);
return
`
${
err
.
message
||
UNKNOWN_ERROR_MESSAGE
}${
err
.
docUri
!==
null
?
`
See
${
buildDocumentationLink
(
err
.
docUri
)}
`
:
''
}
`
;
return
`
${
err
.
message
||
UNKNOWN_ERROR_MESSAGE
}
See
${
buildDocumentationLink
(
err
.
docUri
)}
`
;
};
const
errorHandler
=
(
context
:
Context
)
=>
{
...
...
src/routes/index.ts
View file @
dc5cb26b
...
...
@@ -5,15 +5,26 @@ import operationParser from '../utils/operationParser';
import
pipelineCreator
from
'
../pipeline
'
;
import
senderCreator
from
'
../utils/sender
'
;
import
CError
from
'
../errors/CError
'
;
import
{
CacheConfig
}
from
'
../config/default
'
;
const
defaultOutputCacheConfig
:
CacheConfig
=
{
type
:
'
memory
'
,
options
:
{
limit
:
100
,
},
};
const
indexRoute
=
(
context
:
Context
)
=>
{
const
{
logger
,
config
}
=
context
;
const
cache
=
cacheFactory
(
config
.
caches
.
output
);
const
cache
=
cacheFactory
(
config
.
caches
?
.
output
||
defaultOutputCacheConfig
);
const
sender
=
senderCreator
(
config
);
const
pipeline
=
pipelineCreator
(
context
);
const
basePathRegexp
=
new
RegExp
(
`^
${
config
.
basePath
}
`
);
const
basePathReplacer
=
(
url
:
string
)
=>
config
.
basePath
?
url
.
replace
(
basePathRegexp
,
''
)
:
url
;
const
handler
:
AugmentedRequestHandler
=
async
(
req
,
res
)
=>
{
const
url
=
req
.
url
||
'
/
'
;
const
url
=
basePathReplacer
(
req
.
url
||
'
/
'
)
;
const
cachedResource
=
await
cache
.
get
(
url
);
if
(
cachedResource
)
{
logger
.
info
(
`Cache hit for resource "
${
url
}
"`
);
...
...
src/utils/imageLoader.ts
View file @
dc5cb26b
import
{
Context
}
from
'
..
'
;
import
cache
from
'
../caches/cache
'
;
import
{
CacheConfig
}
from
'
../config/default
'
;
const
defaultInputCache
:
CacheConfig
=
{
type
:
'
none
'
,
options
:
null
,
};
interface
ImageLoader
{
/**
...
...
@@ -11,7 +17,7 @@ interface ImageLoader {
const
imageLoader
=
(
context
:
Context
):
ImageLoader
=>
{
const
{
logger
}
=
context
;
const
inputCache
=
cache
(
context
.
config
.
caches
.
input
);
const
inputCache
=
cache
(
context
.
config
.
caches
?
.
input
||
defaultInputCache
);
return
{
get
:
async
(
url
)
=>
{
const
cached
=
await
inputCache
.
get
(
url
);
...
...
src/utils/misc.ts
View file @
dc5cb26b
...
...
@@ -39,8 +39,10 @@ export const isPercentage = (percentage: string | number | null) =>
export
const
percentageToPixel
=
(
percentage
:
number
,
dimension
:
number
)
=>
Math
.
round
(
percentage
*
dimension
);
export
const
buildDocumentationLink
=
(
doc
:
string
)
=>
`https://caravaggio.ramielcreations.com/docs/
${
doc
}
`
;
export
const
buildDocumentationLink
=
(
doc
:
string
|
null
)
=>
doc
?
`https://caravaggio.ramielcreations.com/docs/
${
doc
}
`
:
'
https://caravaggio.ramielcreations.com/docs
'
;
export
const
compose
=
(...
fns
:
Function
[])
=>
fns
.
reduce
((
f
,
g
)
=>
(...
args
:
unknown
[])
=>
f
(
g
(...
args
)));
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