Skip to content

Commit a35f159

Browse files
authored
feat: support x-forwarded-path (#579)
1 parent 3c19f8d commit a35f159

File tree

5 files changed

+25
-5
lines changed

5 files changed

+25
-5
lines changed

src/config.ts

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ type StorageConfigType = {
5656
tenantId: string
5757
requestUrlLengthLimit: number
5858
requestXForwardedHostRegExp?: string
59+
requestAllowXForwardedPrefix?: boolean
5960
logLevel?: string
6061
logflareEnabled?: boolean
6162
logflareApiKey?: string
@@ -194,6 +195,8 @@ export function getConfig(options?: { reload?: boolean }): StorageConfigType {
194195
'REQUEST_X_FORWARDED_HOST_REGEXP',
195196
'X_FORWARDED_HOST_REGEXP'
196197
),
198+
requestAllowXForwardedPrefix:
199+
getOptionalConfigFromEnv('REQUEST_ALLOW_X_FORWARDED_PATH') === 'true',
197200
requestUrlLengthLimit:
198201
Number(getOptionalConfigFromEnv('REQUEST_URL_LENGTH_LIMIT', 'URL_LENGTH_LIMIT')) || 7_500,
199202
requestTraceHeader: getOptionalConfigFromEnv('REQUEST_TRACE_HEADER', 'REQUEST_ID_HEADER'),

src/http/plugins/signature-v4.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {
1414
serviceKey,
1515
storageS3Region,
1616
isMultitenant,
17+
requestAllowXForwardedPrefix,
1718
s3ProtocolPrefix,
1819
s3ProtocolAllowForwardedHeader,
1920
s3ProtocolEnforceRegion,
@@ -37,13 +38,21 @@ export const signatureV4 = fastifyPlugin(
3738
token,
3839
} = await createServerSignature(request.tenantId, clientSignature)
3940

41+
let storagePrefix = s3ProtocolPrefix
42+
if (
43+
requestAllowXForwardedPrefix &&
44+
typeof request.headers['x-forwarded-prefix'] === 'string'
45+
) {
46+
storagePrefix = request.headers['x-forwarded-prefix']
47+
}
48+
4049
const isVerified = signatureV4.verify(clientSignature, {
4150
url: request.url,
4251
body: request.body as string | ReadableStream | Buffer,
4352
headers: request.headers as Record<string, string | string[]>,
4453
method: request.method,
4554
query: request.query as Record<string, string>,
46-
prefix: s3ProtocolPrefix,
55+
prefix: storagePrefix,
4756
})
4857

4958
if (!isVerified && !sessionToken) {

src/http/routes/tus/lifecycle.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { UploadId } from '@storage/protocols/tus'
1010

1111
import { getConfig } from '../../../config'
1212

13-
const { storageS3Bucket, tusPath } = getConfig()
13+
const { storageS3Bucket, tusPath, requestAllowXForwardedPrefix } = getConfig()
1414
const reExtractFileID = /([^/]+)\/?$/
1515

1616
export const SIGNED_URL_SUFFIX = '/sign'
@@ -92,8 +92,15 @@ export function generateUrl(
9292
}
9393
proto = process.env.NODE_ENV === 'production' ? 'https' : proto
9494

95+
let basePath = path
96+
97+
const forwardedPath = req.headers['x-forwarded-prefix']
98+
if (requestAllowXForwardedPrefix && typeof forwardedPath === 'string') {
99+
basePath = forwardedPath + path
100+
}
101+
95102
const isSigned = req.url?.endsWith(SIGNED_URL_SUFFIX)
96-
const fullPath = isSigned ? `${path}${SIGNED_URL_SUFFIX}` : path
103+
const fullPath = isSigned ? `${basePath}${SIGNED_URL_SUFFIX}` : basePath
97104

98105
if (req.headers['x-forwarded-host']) {
99106
const port = req.headers['x-forwarded-port']

src/internal/monitoring/logger.ts

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ const whitelistHeaders = (headers: Record<string, unknown>) => {
139139
'x-forwarded-proto',
140140
'x-forwarded-host',
141141
'x-forwarded-port',
142+
'x-forwarded-prefix',
142143
'referer',
143144
'content-length',
144145
'x-real-ip',

src/storage/protocols/s3/signature-v4.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export class SignatureV4 {
184184
const serverSignature = this.sign(clientSignature, request)
185185
return crypto.timingSafeEqual(
186186
Buffer.from(clientSignature.signature),
187-
Buffer.from(serverSignature)
187+
Buffer.from(serverSignature.signature)
188188
)
189189
}
190190

@@ -223,7 +223,7 @@ export class SignatureV4 {
223223
serverCredentials.service
224224
)
225225

226-
return this.hmac(signingKey, stringToSign).toString('hex')
226+
return { signature: this.hmac(signingKey, stringToSign).toString('hex'), canonicalRequest }
227227
}
228228

229229
protected getPayloadHash(clientSignature: ClientSignature, request: SignatureRequest) {

0 commit comments

Comments
 (0)