Skip to content

Commit 9317460

Browse files
committed
fix: don't try to extract protocol
1 parent a1503df commit 9317460

File tree

6 files changed

+53
-39
lines changed

6 files changed

+53
-39
lines changed

extensions/image-processing-api/POSTINSTALL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ encodeURIComponent(JSON.stringify(operations));
2929

3030
3. Call the deployed `process` Cloud Function:
3131

32-
[https://${param:LOCATION}-${param:PROJECT_ID}.cloudfunctions.net/ext-${param:EXT_INSTANCE_ID}-handler/process?operations=%5B%7B%22operation%22%3A%22input%22%2C%22type%22%3A%22url%22%2C%22url%22%3A%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1663659552548-25d7771802c9%3Fixlib%3Drb-1.2.1%26ixid%3DMnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8%26auto%3Dformat%26fit%3Dcrop%26w%3D774%26q%3D80%22%7D%2C%7B%22operation%22%3A%22grayscale%22%7D%2C%7B%22operation%22%3A%22output%22%2C%22format%22%3A%22webp%22%7D%5D](https://${param:LOCATION}-${param:PROJECT_ID}.cloudfunctions.net/ext-image-processing-api-handler/process?operations=%5B%7B%22operation%22%3A%22input%22%2C%22type%22%3A%22url%22%2C%22url%22%3A%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1663659552548-25d7771802c9%3Fixlib%3Drb-1.2.1%26ixid%3DMnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8%26auto%3Dformat%26fit%3Dcrop%26w%3D774%26q%3D80%22%7D%2C%7B%22operation%22%3A%22grayscale%22%7D%2C%7B%22operation%22%3A%22output%22%2C%22format%22%3A%22webp%22%7D%5D)
32+
[https://${param:LOCATION}-${param:PROJECT_ID}.cloudfunctions.net/ext-${param:EXT_INSTANCE_ID}-handler/process?operations=%5B%7B%22operation%22%3A%22input%22%2C%22type%22%3A%22url%22%2C%22url%22%3A%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1663659552548-25d7771802c9%3Fixlib%3Drb-1.2.1%26ixid%3DMnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8%26auto%3Dformat%26fit%3Dcrop%26w%3D774%26q%3D80%22%7D%2C%7B%22operation%22%3A%22grayscale%22%7D%2C%7B%22operation%22%3A%22output%22%2C%22format%22%3A%22webp%22%7D%5D](https://${param:LOCATION}-${param:PROJECT_ID}.cloudfunctions.net/ext-${param:EXT_INSTANCE_ID}-handler/process?operations=%5B%7B%22operation%22%3A%22input%22%2C%22type%22%3A%22url%22%2C%22url%22%3A%22https%3A%2F%2Fimages.unsplash.com%2Fphoto-1663659552548-25d7771802c9%3Fixlib%3Drb-1.2.1%26ixid%3DMnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8%26auto%3Dformat%26fit%3Dcrop%26w%3D774%26q%3D80%22%7D%2C%7B%22operation%22%3A%22grayscale%22%7D%2C%7B%22operation%22%3A%22output%22%2C%22format%22%3A%22webp%22%7D%5D)
3333

3434
The result will be a grayscaled version of the image, in WebP format.
3535

extensions/image-processing-api/functions/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
"emulator:local": "FIREBASE_STORAGE_EMULATOR_HOST='localhost:9199' firebase ext:dev:emulators:start --test-config=__tests__/test-firebase.json --test-params=__tests__/test-params.env --project=extensions-testing --import=./__tests__/data",
1111
"generate-readme": "firebase ext:info .. --markdown > ../README.md",
1212
"deploy": "firebase ext:install ../ --project=extensions-testing",
13-
"postinstall": "npm run copy-types || exit 0",
1413
"test": "vitest run",
1514
"test:watch": "vitest",
1615
"test:ui": "vitest --ui",

extensions/image-processing-api/functions/src/index.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
fileMetadataBufferKeys,
3434
omitKeys,
3535
} from './utils';
36-
import { Operation, ValidatedOperation } from './types';
36+
import { NotFoundError, Operation, ValidatedOperation } from './types';
3737
import { extensionConfiguration } from './config';
3838
import sharp from 'sharp';
3939

@@ -173,23 +173,27 @@ app.get(
173173
// to be treated as an error handler.
174174

175175
app.use(function handleError(
176-
error: Error,
176+
error: Error & { statusCode?: number },
177177
req: Request,
178178
res: Response,
179179
// eslint-disable-next-line @typescript-eslint/no-unused-vars
180180
next: express.NextFunction,
181181
) {
182-
if (error instanceof StructError || error instanceof AssertionError) {
182+
if (error instanceof NotFoundError) {
183+
functions.logger.warn(error.message, {
184+
url: req.url,
185+
query: req.query,
186+
});
187+
res.status(error.statusCode).send(error.message);
188+
} else if (error instanceof StructError || error instanceof AssertionError) {
183189
functions.logger.warn(error.message, {
184190
url: req.url,
185191
query: req.query,
186192
});
187193
res.status(400).send(error.message);
188194
} else {
189195
functions.logger.error(
190-
'An error occurred processing a request, please report this issue to the GitHub ' +
191-
'repository for this extension and include this log entry with your report (omit any ' +
192-
'sensitive data).',
196+
'An error occurred processing a request, please report this issue to the GitHub repository for this extension and include this log entry with your report (omit any sensitive data).',
193197
{
194198
url: req.url,
195199
query: req.query,

extensions/image-processing-api/functions/src/operations/input.ts

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ import * as superstruct from 'superstruct';
1818
import express from 'express';
1919

2020
import * as utils from '../utils';
21-
import { Operation, OperationAction, OperationBuilder } from '../types';
21+
import {
22+
NotFoundError,
23+
Operation,
24+
OperationAction,
25+
OperationBuilder,
26+
} from '../types';
2227
import { AssertionError } from 'assert';
2328
import { fetchImageBufferFromUrl } from '../utils';
2429
import { extensionConfiguration } from '../config';
@@ -197,42 +202,25 @@ async function fetchPathUrl(
197202
message: 'Request object is required for path type inputs.',
198203
});
199204
}
205+
// const forwardedProto = req.headers['x-forwarded-proto'] || req.protocol;
206+
const forwardedHost = req.headers['x-forwarded-host'] || req.headers['host'];
200207

201-
// Extract hostname from request
202-
const origin = (req.headers.origin as string) || '';
203-
const referer = (req.headers.referer as string) || '';
204-
const host = req.headers.host || '';
205-
206-
let baseUrl = '';
207-
208-
// Try to get the base URL from various sources
209-
if (origin) {
210-
baseUrl = origin;
211-
} else if (referer) {
212-
try {
213-
const url = new URL(referer);
214-
baseUrl = `${url.protocol}//${url.host}`;
215-
} catch (e) {
216-
// Invalid URL format in referer
217-
}
218-
} else if (host) {
219-
const protocol = req.secure ? 'https:' : 'http:';
220-
baseUrl = `${protocol}//${host}`;
208+
if (!forwardedHost) {
209+
throw new NotFoundError('Request host is not defined.');
221210
}
222211

223-
if (!baseUrl) {
224-
throw new AssertionError({
225-
message: `Could not determine request hostname for path URL.`,
226-
});
212+
const fullUrl = `https://${forwardedHost}${options.path}`;
213+
let imageBuffer: Buffer;
214+
try {
215+
imageBuffer = await fetchImageBufferFromUrl(fullUrl);
216+
} catch (error) {
217+
throw new NotFoundError(`Image not found at ${fullUrl}`);
227218
}
228219

229-
// Construct the full URL
230-
const fullUrl = `${baseUrl}${options.path}`;
231-
232220
return [
233221
{
234222
method: 'constructor',
235-
arguments: [await fetchImageBufferFromUrl(fullUrl)],
223+
arguments: [imageBuffer],
236224
},
237225
];
238226
}

extensions/image-processing-api/functions/src/types.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,26 @@ export interface OperationAction {
6767
method: string;
6868
arguments: unknown[];
6969
}
70+
71+
/**
72+
* Custom error class for operation related errors.
73+
*/
74+
export class OperationError extends Error {
75+
public statusCode: number;
76+
77+
constructor(message: string, statusCode = 400) {
78+
super(message);
79+
this.name = 'OperationError';
80+
this.statusCode = statusCode;
81+
}
82+
}
83+
84+
/**
85+
* NotFoundError extends OperationError with a default status code of 404.
86+
*/
87+
export class NotFoundError extends OperationError {
88+
constructor(message = 'Not Found') {
89+
super(message, 404);
90+
this.name = 'NotFoundError';
91+
}
92+
}

extensions/image-processing-api/functions/tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"compilerOptions": {
33
"target": "ES2020",
44
"lib": ["ES2020"],
5-
"types": ["node", "jest"],
5+
"types": ["node"],
66
"allowJs": true,
77
"skipLibCheck": true,
88
"strict": false,
@@ -13,7 +13,7 @@
1313
"moduleResolution": "node",
1414
"resolveJsonModule": true,
1515
"isolatedModules": true,
16-
"outDir": "lib"
16+
"outDir": "./lib"
1717
},
1818
"exclude": ["node_modules", "__tests__"],
1919
"include": ["src"]

0 commit comments

Comments
 (0)