@exabugs/dynamodb-client 1.5.3 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/handler.cjs +3 -3
- package/dist/server/media/magicBytes.d.ts.map +1 -1
- package/dist/server/media/magicBytes.js +17 -14
- package/dist/server/media/magicBytes.js.map +1 -1
- package/dist/server/media/media-handler.d.ts.map +1 -1
- package/dist/server/media/media-handler.js +38 -4
- package/dist/server/media/media-handler.js.map +1 -1
- package/dist/server/media/metadata.d.ts +29 -0
- package/dist/server/media/metadata.d.ts.map +1 -0
- package/dist/server/media/metadata.js +57 -0
- package/dist/server/media/metadata.js.map +1 -0
- package/dist/server/media/presign.d.ts.map +1 -1
- package/dist/server/media/presign.js +18 -1
- package/dist/server/media/presign.js.map +1 -1
- package/dist/server/media/process-handler-dlq.d.ts +0 -13
- package/dist/server/media/process-handler-dlq.d.ts.map +1 -1
- package/dist/server/media/process-handler-dlq.js +49 -7
- package/dist/server/media/process-handler-dlq.js.map +1 -1
- package/dist/server/media/process-handler.d.ts.map +1 -1
- package/dist/server/media/process-handler.js +40 -25
- package/dist/server/media/process-handler.js.map +1 -1
- package/dist/server/media/types.d.ts +1 -1
- package/dist/server/media/types.d.ts.map +1 -1
- package/dist/server/media/upload-handler.d.ts +50 -0
- package/dist/server/media/upload-handler.d.ts.map +1 -0
- package/dist/server/media/upload-handler.js +115 -0
- package/dist/server/media/upload-handler.js.map +1 -0
- package/dist/server/media-handler.cjs +27 -3
- package/dist/server/media-handler.cjs.map +2 -2
- package/dist/server/media-process-handler-dlq.cjs +25496 -13553
- package/dist/server/media-process-handler-dlq.cjs.map +4 -4
- package/dist/server/media-process-handler.cjs +648 -536
- package/dist/server/media-process-handler.cjs.map +4 -4
- package/dist/sharp-layer.zip +0 -0
- package/package.json +5 -1
- package/terraform/media/README.md +4 -1
- package/terraform/media/main.tf +86 -13
- package/terraform/media/variables.tf +33 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/media/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,mBAAmB;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/media/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,mBAAmB;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* presign発行・署名付きURL発行を扱うLambda Function URL用ハンドラー(標準実装)
|
|
3
|
+
*
|
|
4
|
+
* 「誰にpresign/署名URLを発行してよいか」の判断はこのライブラリの関心事ではない
|
|
5
|
+
* (詳細: docs/media-design.md)。このハンドラーは`authorize`フックを通じて
|
|
6
|
+
* 呼び出し側アプリの認証・認可ロジックを注入できるようにする。
|
|
7
|
+
*
|
|
8
|
+
* より高度な認可(例: リソース単位の権限チェック)が必要な場合、呼び出し側は
|
|
9
|
+
* このハンドラーを使わず、`./presign.js`・`./sign.js`を自前のルーティング・
|
|
10
|
+
* 認可レイヤーから直接呼び出すこともできる。
|
|
11
|
+
*/
|
|
12
|
+
import type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from 'aws-lambda';
|
|
13
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
14
|
+
import { SSMClient } from '@aws-sdk/client-ssm';
|
|
15
|
+
/**
|
|
16
|
+
* リクエストを認可し、presign発行時にpolicyへ固定するメタデータを返す。
|
|
17
|
+
* 認可できない場合はnullを返す(401を返す)。
|
|
18
|
+
*/
|
|
19
|
+
export type AuthorizeFn = (event: APIGatewayProxyEventV2) => Promise<Record<string, string> | null>;
|
|
20
|
+
export interface UploadHandlerConfig {
|
|
21
|
+
bucket: string;
|
|
22
|
+
imagePolicyParam: string;
|
|
23
|
+
signingPrivateKeyParam: string;
|
|
24
|
+
keyPairId: string;
|
|
25
|
+
baseUrl: string;
|
|
26
|
+
authorize: AuthorizeFn;
|
|
27
|
+
signExpiresInSeconds?: number;
|
|
28
|
+
s3Client?: S3Client;
|
|
29
|
+
ssmClient?: SSMClient;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 設定を注入してLambda Function URLハンドラーを生成する。
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* export const handler = createUploadHandler({
|
|
37
|
+
* bucket: process.env.MEDIA_BUCKET!,
|
|
38
|
+
* imagePolicyParam: process.env.IMAGE_POLICY_PARAM!,
|
|
39
|
+
* signingPrivateKeyParam: process.env.SIGNING_PRIVATE_KEY_PARAM!,
|
|
40
|
+
* keyPairId: process.env.CLOUDFRONT_KEY_PAIR_ID!,
|
|
41
|
+
* baseUrl: process.env.MEDIA_BASE_URL!,
|
|
42
|
+
* authorize: async (event) => {
|
|
43
|
+
* const userId = await verifyMyAppJwt(event.headers.authorization);
|
|
44
|
+
* return userId ? { ownerId: userId } : null;
|
|
45
|
+
* },
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function createUploadHandler(config: UploadHandlerConfig): (event: APIGatewayProxyEventV2) => Promise<APIGatewayProxyStructuredResultV2>;
|
|
50
|
+
//# sourceMappingURL=upload-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-handler.d.ts","sourceRoot":"","sources":["../../../src/server/media/upload-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,sBAAsB,EAAE,iCAAiC,EAAE,MAAM,YAAY,CAAC;AAE5F,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAWhD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;AAEpG,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AA0FD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,mBAAmB,GAC1B,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,iCAAiC,CAAC,CAiC/E"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
import { SSMClient } from '@aws-sdk/client-ssm';
|
|
3
|
+
import { createLogger } from '../../shared/index.js';
|
|
4
|
+
import { generatePresignedUpload } from './presign.js';
|
|
5
|
+
import { signMediaUrl } from './sign.js';
|
|
6
|
+
import { getImagePolicy, getSigningPrivateKey } from './ssmParams.js';
|
|
7
|
+
const logger = createLogger({ service: 'media-upload-handler' });
|
|
8
|
+
const DEFAULT_SIGN_EXPIRES_IN_SECONDS = 3600;
|
|
9
|
+
function jsonResponse(statusCode, body) {
|
|
10
|
+
return {
|
|
11
|
+
statusCode,
|
|
12
|
+
headers: { 'Content-Type': 'application/json' },
|
|
13
|
+
body: JSON.stringify(body),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function parseBody(event) {
|
|
17
|
+
if (!event.body)
|
|
18
|
+
return {};
|
|
19
|
+
const raw = event.isBase64Encoded
|
|
20
|
+
? Buffer.from(event.body, 'base64').toString('utf-8')
|
|
21
|
+
: event.body;
|
|
22
|
+
return JSON.parse(raw);
|
|
23
|
+
}
|
|
24
|
+
async function handlePresign(event, config, s3Client, ssmClient, metadata, requestId) {
|
|
25
|
+
const body = parseBody(event);
|
|
26
|
+
if (!body.contentType || !body.fileSize) {
|
|
27
|
+
return jsonResponse(400, { error: 'contentType and fileSize are required' });
|
|
28
|
+
}
|
|
29
|
+
const imagePolicy = await getImagePolicy(ssmClient, config.imagePolicyParam);
|
|
30
|
+
const result = await generatePresignedUpload({
|
|
31
|
+
s3Client,
|
|
32
|
+
bucket: config.bucket,
|
|
33
|
+
contentType: body.contentType,
|
|
34
|
+
originalFilename: body.originalFilename,
|
|
35
|
+
fileSize: body.fileSize,
|
|
36
|
+
allowedContentTypes: imagePolicy.allowedContentTypes,
|
|
37
|
+
maxUploadSize: imagePolicy.maxUploadSize,
|
|
38
|
+
metadata,
|
|
39
|
+
});
|
|
40
|
+
logger.info('Presign issued', { requestId, fileId: result.fileId });
|
|
41
|
+
return jsonResponse(200, result);
|
|
42
|
+
}
|
|
43
|
+
async function handleSign(event, config, ssmClient, requestId) {
|
|
44
|
+
const body = parseBody(event);
|
|
45
|
+
if (!Array.isArray(body.items) || body.items.length === 0) {
|
|
46
|
+
return jsonResponse(400, { error: 'items is required and must be non-empty' });
|
|
47
|
+
}
|
|
48
|
+
const privateKey = await getSigningPrivateKey(ssmClient, config.signingPrivateKeyParam);
|
|
49
|
+
const expiresInSeconds = config.signExpiresInSeconds ?? DEFAULT_SIGN_EXPIRES_IN_SECONDS;
|
|
50
|
+
const items = body.items.map((item) => {
|
|
51
|
+
if (!item.fileId) {
|
|
52
|
+
throw new Error('Each item must have fileId');
|
|
53
|
+
}
|
|
54
|
+
return signMediaUrl({
|
|
55
|
+
fileId: item.fileId,
|
|
56
|
+
width: item.width,
|
|
57
|
+
keyPairId: config.keyPairId,
|
|
58
|
+
privateKey,
|
|
59
|
+
baseUrl: config.baseUrl,
|
|
60
|
+
expiresInSeconds,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
logger.info('Media URLs signed', { requestId, count: items.length });
|
|
64
|
+
return jsonResponse(200, { items });
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 設定を注入してLambda Function URLハンドラーを生成する。
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* export const handler = createUploadHandler({
|
|
72
|
+
* bucket: process.env.MEDIA_BUCKET!,
|
|
73
|
+
* imagePolicyParam: process.env.IMAGE_POLICY_PARAM!,
|
|
74
|
+
* signingPrivateKeyParam: process.env.SIGNING_PRIVATE_KEY_PARAM!,
|
|
75
|
+
* keyPairId: process.env.CLOUDFRONT_KEY_PAIR_ID!,
|
|
76
|
+
* baseUrl: process.env.MEDIA_BASE_URL!,
|
|
77
|
+
* authorize: async (event) => {
|
|
78
|
+
* const userId = await verifyMyAppJwt(event.headers.authorization);
|
|
79
|
+
* return userId ? { ownerId: userId } : null;
|
|
80
|
+
* },
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function createUploadHandler(config) {
|
|
85
|
+
const s3Client = config.s3Client ?? new S3Client({ region: process.env.AWS_REGION });
|
|
86
|
+
const ssmClient = config.ssmClient ?? new SSMClient({ region: process.env.AWS_REGION });
|
|
87
|
+
return async (event) => {
|
|
88
|
+
const requestId = event.requestContext.requestId;
|
|
89
|
+
const method = event.requestContext.http.method;
|
|
90
|
+
const path = event.rawPath;
|
|
91
|
+
try {
|
|
92
|
+
const metadata = await config.authorize(event);
|
|
93
|
+
if (!metadata) {
|
|
94
|
+
return jsonResponse(401, { error: 'Unauthorized' });
|
|
95
|
+
}
|
|
96
|
+
if (method === 'POST' && path.endsWith('/presign')) {
|
|
97
|
+
return await handlePresign(event, config, s3Client, ssmClient, metadata, requestId);
|
|
98
|
+
}
|
|
99
|
+
if (method === 'POST' && path.endsWith('/sign')) {
|
|
100
|
+
return await handleSign(event, config, ssmClient, requestId);
|
|
101
|
+
}
|
|
102
|
+
return jsonResponse(404, { error: 'Not found' });
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
logger.error('Upload handler error', {
|
|
106
|
+
requestId,
|
|
107
|
+
error: error instanceof Error ? error.message : String(error),
|
|
108
|
+
});
|
|
109
|
+
return jsonResponse(400, {
|
|
110
|
+
error: error instanceof Error ? error.message : 'Bad request',
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=upload-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-handler.js","sourceRoot":"","sources":["../../../src/server/media/upload-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// @exabugs/dynamodb-client v1.
|
|
2
|
-
// Built: 2026-10-
|
|
1
|
+
// @exabugs/dynamodb-client v1.6.0
|
|
2
|
+
// Built: 2026-10-04T23:59:48.659Z
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -57323,6 +57323,16 @@ var ssmClient = new import_client_ssm2.SSMClient({ region: process.env.AWS_REGIO
|
|
|
57323
57323
|
var MAX_INPUT_PIXELS = 1e8;
|
|
57324
57324
|
var CACHE_CONTROL_IMMUTABLE = "public, max-age=31536000, immutable";
|
|
57325
57325
|
var CACHE_CONTROL_NO_STORE = "no-store";
|
|
57326
|
+
var MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
57327
|
+
var QUALITY_FALLBACK_STEPS = [80, 60, 40];
|
|
57328
|
+
function payloadTooLargeResponse(message) {
|
|
57329
|
+
return {
|
|
57330
|
+
statusCode: 413,
|
|
57331
|
+
headers: { "Cache-Control": CACHE_CONTROL_NO_STORE, "Content-Type": "text/plain" },
|
|
57332
|
+
body: message
|
|
57333
|
+
};
|
|
57334
|
+
}
|
|
57335
|
+
__name(payloadTooLargeResponse, "payloadTooLargeResponse");
|
|
57326
57336
|
function notFoundResponse(message) {
|
|
57327
57337
|
return {
|
|
57328
57338
|
statusCode: 404,
|
|
@@ -57422,7 +57432,13 @@ async function handler(event) {
|
|
|
57422
57432
|
}
|
|
57423
57433
|
let resized;
|
|
57424
57434
|
try {
|
|
57425
|
-
|
|
57435
|
+
for (const quality of QUALITY_FALLBACK_STEPS) {
|
|
57436
|
+
const buffer = await (0, import_sharp.default)(master, { limitInputPixels: MAX_INPUT_PIXELS }).resize(width, width, { fit: "inside", withoutEnlargement: true }).jpeg({ quality }).toBuffer();
|
|
57437
|
+
if (buffer.length <= MAX_RESPONSE_BYTES) {
|
|
57438
|
+
resized = buffer;
|
|
57439
|
+
break;
|
|
57440
|
+
}
|
|
57441
|
+
}
|
|
57426
57442
|
} catch (error2) {
|
|
57427
57443
|
logger2.warn("Resize not applicable (master is not a processable raster image)", {
|
|
57428
57444
|
requestId,
|
|
@@ -57431,6 +57447,14 @@ async function handler(event) {
|
|
|
57431
57447
|
});
|
|
57432
57448
|
return badRequestResponse("Resize is not applicable to this file");
|
|
57433
57449
|
}
|
|
57450
|
+
if (!resized) {
|
|
57451
|
+
logger2.warn("Resized output exceeds response size limit even at minimum quality", {
|
|
57452
|
+
requestId,
|
|
57453
|
+
fileId,
|
|
57454
|
+
width
|
|
57455
|
+
});
|
|
57456
|
+
return payloadTooLargeResponse("Resized output is too large to return");
|
|
57457
|
+
}
|
|
57434
57458
|
await s3Client.send(
|
|
57435
57459
|
new import_client_s3.PutObjectCommand({
|
|
57436
57460
|
Bucket: bucket,
|