Skip to content

Commit d2a6fea

Browse files
authored
seperate some proxy logic
1 parent c32a945 commit d2a6fea

File tree

5 files changed

+153
-26
lines changed

5 files changed

+153
-26
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ The following transformations have been implemented (Note that it is not planned
164164
| [`Max Bytes`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#max-bytes) | :white_check_mark: |
165165
| [`Background`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#background) | :white_check_mark: |
166166
| [`Sharpen`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#sharpen) | :white_check_mark: |
167-
| [`Watermark`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#watermark) | :x: |
168-
| [`Preset`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#preset) | :x: |
169-
| [`Cache Buster`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#cache-buster) | :x: |
170-
| [`Strip Metadata`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#strip-metadata) | :x: |
171-
| [`Strip Color Profile`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#strip-color-profile) | :x: |
172-
| [`Auto Rotate`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#auto-rotate) | :x: |
173-
| [`Filename`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#filename) | :x: |
167+
| [`Watermark`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#watermark) | :white_check_mark: |
168+
| [`Preset`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#preset) | :white_check_mark: |
169+
| [`Cache Buster`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#cache-buster) | :white_check_mark: |
170+
| [`Strip Metadata`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#strip-metadata) | :white_check_mark: |
171+
| [`Strip Color Profile`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#strip-color-profile) | :white_check_mark: |
172+
| [`Auto Rotate`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#auto-rotate) | :white_check_mark: |
173+
| [`Filename`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#filename) | :white_check_mark: |
174174
| [`Format`](https://github.com/imgproxy/imgproxy/blob/master/docs/generating_the_url_advanced.md#format) | :white_check_mark: |

example/server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ app.prepare().then(() => {
1515
const { pathname, query } = parsedUrl;
1616

1717
if (pathname === imgProxy.IMGPROXY_ENDPOINT) {
18-
imgProxy.imageOptimizer(new URL('http://localhost:4000/'), query, res, {
18+
imgProxy.handle(new URL('http://localhost:4000/'), query, res, {
1919
signature: {
2020
key: '91bdcda48ce22cd7d8d3a0eda930b3db1762bc1cba5dc13542e723b68fe55d6f9d18199cbe35191a45faf22593405cad0fe76ffec67d24f8aee861ac8fe44d96',
2121
salt: '72456c286761260f320391fe500fcec53755958dabd288867a6db072e1bc1dbd84b15079838a83a715edc1ecad50c3ce91dd8fdef6f981816fa274f91d8ecf06',
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
enum WatermarkPosition {
2+
CENTER = 'ce',
3+
NORTH = 'no',
4+
SOUTH = 'so',
5+
EAST = 'ea',
6+
WEST = 'we',
7+
NORTH_EAST = 'noea',
8+
NORTH_WEST = 'nowe',
9+
SOUTH_EAST = 'soea',
10+
SOUTH_WEST = 'sowe',
11+
REPLICATE = 're',
12+
}
13+
14+
export default WatermarkPosition;

src/index.tsx

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import ResizeType from './enums/resize-type.enum';
1212

1313
const IMGPROXY_ENDPOINT = '/_next/imgproxy';
1414
const SRC_REGEX = /^[^/.]+\/.+[^/]$/;
15-
1615
const FORWARDED_HEADERS = [
1716
'date',
1817
'expires',
@@ -22,6 +21,49 @@ const FORWARDED_HEADERS = [
2221
'content-disposition',
2322
];
2423

24+
/**
25+
* Generates the signature for the specified uery
26+
* @param key The signature key
27+
* @param salt The signature salt$
28+
* @param buff The full request path
29+
* @returns The imgproxy signature
30+
*/
31+
const generateSignature = (key: string, salt: string, buff: string): string => {
32+
const hmac = createHmac('sha256', Buffer.from(key, 'hex'));
33+
hmac.update(Buffer.from(salt, 'hex'));
34+
hmac.update(buff);
35+
return hmac.digest().toString('base64url');
36+
};
37+
38+
/**
39+
* Builds the final reuest path to retrieve
40+
* an image from the imgproxy instance
41+
* @param src The source file
42+
* @param options The imgproxy options
43+
* @returns The imgproxy request path
44+
*/
45+
const buildRequestPath = (
46+
src: string,
47+
options?: {
48+
imgproxyParams?: string;
49+
signature?: {
50+
key: string;
51+
salt: string;
52+
};
53+
},
54+
): string => {
55+
const { imgproxyParams, signature } = options ?? {};
56+
57+
const paramString = imgproxyParams ? `${imgproxyParams}/` : '';
58+
const requestPath = `/${paramString}plain/s3://${src}`;
59+
60+
const urlSignature = signature
61+
? generateSignature(signature.key, signature.salt, requestPath)
62+
: '';
63+
64+
return `/${urlSignature}${requestPath}`;
65+
};
66+
2567
type ImageOptimizerOptions = {
2668
signature?: {
2769
key: string;
@@ -32,19 +74,20 @@ type ImageOptimizerOptions = {
3274
forwardedHeaders?: string[];
3375
};
3476

35-
const generateSignature = (key: string, salt: string, buff: string): string => {
36-
const hmac = createHmac('sha256', Buffer.from(key, 'hex'));
37-
hmac.update(Buffer.from(salt, 'hex'));
38-
hmac.update(buff);
39-
return hmac.digest().toString('base64url');
40-
};
41-
42-
const imageOptimizer = (
77+
/**
78+
* Handles an image request
79+
* @param imgproxyBaseUrl The URL to the imgproxy instance
80+
* @param query The URL query generated by the {@link ImgProxyParamBuilder}
81+
* @param res The response to which the resulting file should be piped to
82+
* @param options Optional configuration options for the imgproxy connection
83+
* @returns
84+
*/
85+
const handle = (
4386
imgproxyBaseUrl: URL,
4487
query: ParsedUrlQuery,
4588
res: ServerResponse,
4689
options?: ImageOptimizerOptions,
47-
) => {
90+
): void => {
4891
const { src, params } = query;
4992
const { authToken, bucketWhitelist, forwardedHeaders, signature } =
5093
options ?? {};
@@ -64,12 +107,10 @@ const imageOptimizer = (
64107
return;
65108
}
66109

67-
const paramString = params ? `${params}/` : '';
68-
const requestPath = `/${paramString}plain/s3://${src}`;
69-
70-
const urlSignature = signature
71-
? generateSignature(signature.key, signature.salt, requestPath)
72-
: '';
110+
const requestPath = buildRequestPath(src, {
111+
imgproxyParams: params as string,
112+
signature,
113+
});
73114

74115
const reqMethod = imgproxyBaseUrl.protocol.startsWith('https')
75116
? httpsRequest
@@ -79,7 +120,7 @@ const imageOptimizer = (
79120
{
80121
hostname: imgproxyBaseUrl.hostname,
81122
...(imgproxyBaseUrl.port ? { port: imgproxyBaseUrl.port } : {}),
82-
path: `/${urlSignature}${requestPath}`,
123+
path: requestPath,
83124
method: 'GET',
84125
headers: {
85126
...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),
@@ -161,7 +202,8 @@ export default ProxyImage;
161202
export {
162203
IMGPROXY_ENDPOINT,
163204
buildProxyImagePath,
164-
imageOptimizer,
205+
handle,
206+
generateSignature,
165207
ImgProxyParamBuilder,
166208
GravityType,
167209
ResizeType,

src/param-builder.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import GravityType from './enums/gravity-type.enum';
22
import ResizeType from './enums/resize-type.enum';
3+
import WatermarkPosition from './enums/watermark-position.enum';
34

45
type ForwardType = Partial<ImgProxyParamBuilder> & {
56
modifiers: string[];
@@ -189,6 +190,33 @@ class ImgProxyParamBuilder {
189190
return this;
190191
}
191192

193+
addWatermark<T extends ForwardType>(
194+
this: T,
195+
options: {
196+
opacity: number;
197+
position?: WatermarkPosition;
198+
offset?: {
199+
x: number;
200+
y: number;
201+
};
202+
scale?: number;
203+
},
204+
): Omit<T, 'addWatermark'> {
205+
const { opacity, position, offset, scale } = options;
206+
207+
this.modifiers.push(
208+
[
209+
'wm',
210+
opacity,
211+
position ?? WatermarkPosition.CENTER,
212+
offset?.x ?? 0,
213+
offset?.y ?? 0,
214+
scale ?? 0,
215+
].join(':'),
216+
);
217+
return this;
218+
}
219+
192220
blur<T extends ForwardType>(this: T, sigma: number): Omit<T, 'blur'> {
193221
this.modifiers.push(['blur', sigma].join(':'));
194222
return this;
@@ -198,6 +226,49 @@ class ImgProxyParamBuilder {
198226
this.modifiers.push(['format', format].join(':'));
199227
return this;
200228
}
229+
230+
useCacheBuster<T extends ForwardType>(
231+
this: T,
232+
buster: string,
233+
): Omit<T, 'useCacheBuster'> {
234+
this.modifiers.push(['cb', buster].join(':'));
235+
return this;
236+
}
237+
238+
stripMetadata<T extends ForwardType>(this: T): Omit<T, 'stripMetadata'> {
239+
this.modifiers.push(['sm', 1].join(':'));
240+
return this;
241+
}
242+
243+
stripColorProfile<T extends ForwardType>(
244+
this: T,
245+
): Omit<T, 'stripColorProfile'> {
246+
this.modifiers.push(['scp', 1].join(':'));
247+
return this;
248+
}
249+
250+
autoRotate<T extends ForwardType>(this: T): Omit<T, 'autoRotate'> {
251+
this.modifiers.push(['ar', 1].join(':'));
252+
return this;
253+
}
254+
255+
setFilename<T extends ForwardType>(
256+
this: T,
257+
fileName: string,
258+
): Omit<T, 'setFilename'> {
259+
this.modifiers.push(['fn', fileName].join(':'));
260+
return this;
261+
}
262+
263+
usePreset<T extends ForwardType>(
264+
this: T,
265+
presets: string | string[],
266+
): Omit<T, 'usePreset'> {
267+
this.modifiers.push(
268+
['preset', ...(Array.isArray(presets) ? presets : [presets])].join(':'),
269+
);
270+
return this;
271+
}
201272
}
202273

203274
export default ImgProxyParamBuilder;

0 commit comments

Comments
 (0)