Hello Uppy team,
I’m experiencing an issue where custom headers specified in the AwsS3 plugin are not being passed to my Companion server. I’ve tried multiple approaches based on various GitHub issues and forum posts, but none have worked.
Environment
- Uppy version: 4.17.0 (CDN)
- Companion version: 5.8.0
- Node.js: 18.20.8
- Deployment: Companion running on separate subdomain
What I’m trying to achieve
I need to pass user-specific information (x-user-id and x-database-id)
from the client to Companion so I can organize S3 uploads in
user-specific folders using a custom getKey function.
Current Setup
Client-side (Uppy configuration):
const { Uppy, Dashboard, AwsS3, OneDrive, GoogleDrive } = window.Uppy;
const uppy = new Uppy({
debug: true,
// ... other config
});
// Tried setting metadata
uppy.setMeta({
userId: '{{ request.user.id }}',
databaseId: '{{ database.index }}'
});
// Tried multiple header configurations
uppy.use(AwsS3, {
endpoint: 'https://uploads.domain.com',
headers: { // Also tried 'companionHeaders'
'x-requested-with': 'XMLHttpRequest',
'x-user-id': '{{ request.user.id }}',
'x-database-id': '{{ database.index }}'
}
});
Server-side (Companion configuration):
const app = express();
// Added custom CORS middleware before Companion
app.use((req, res, next) => {
res.header('Access-Control-Allow-Headers',
'Authorization, Origin, Content-Type, Accept, uppy-auth-token,
uppy-versions, x-user-id, x-database-id, x-requested-with'
);
res.header('Access-Control-Expose-Headers',
'Access-Control-Allow-Headers');
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Origin', req.headers.origin ||
'*');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS,
PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Credentials', 'true');
return res.sendStatus(200);
}
next();
});
const companionOptions = {
corsOrigins: true,
s3: {
key: process.env.COMPANION_AWS_KEY,
secret: process.env.COMPANION_AWS_SECRET,
bucket: process.env.COMPANION_AWS_BUCKET,
region: process.env.COMPANION_AWS_REGION || 'us-east-1',
getKey: (req, filename, metadata) => {
// Trying to get data from both metadata and headers
let userId = metadata?.userId || req.headers['x-user-id'] ||
'anonymous';
let databaseId = metadata?.databaseId ||
req.headers['x-database-id'] || 'default';
const key = `${userId}/${databaseId}/raw/${filename}`;
console.log('Generating S3 key:', {
userId, databaseId, filename, key,
metadata, headers: req.headers
});
return key;
}
},
// ... other config
};
What I’ve tried
- Using headers property in AwsS3 plugin configuration
- Using companionHeaders property (found in some GitHub issues)
- Setting metadata with uppy.setMeta()
- Adding custom CORS middleware before Companion
- Exposing Access-Control-Allow-Headers in CORS response
- Using lowercase header names (Node.js normalization)
- Trying AwsS3Multipart instead of AwsS3
The Problem
strong text
When I log the incoming requests in Companion:
- The custom headers (x-user-id, x-database-id) are not present in
req.headers - The metadata object in getKey is either undefined or doesn’t contain
my custom fields - Files are always uploaded to the anonymous/default/raw/ path
Debug Output
From my debug middleware, I can see Uppy IS sending the standard
headers, but my custom headers are missing:
=== Incoming Request ===
Method: POST
URL: /s3/params
Headers: {
“host”: “uploads.domain.com”,
“content-type”: “application/json”,
“accept”: “application/json”,
“uppy-versions”: “@uppy/aws-s3=…”,
// … other standard headers
// But NO x-user-id or x-database-id!
}
What is the correct way to pass custom headers from the AwsS3 plugin to Companion in the latest versions?
I’ve seen various GitHub issues (#2465, #1059, #2089) mentioning
similar problems, but the solutions don’t seem to work with the current
versions.
Any help would be greatly appreciated! This is blocking our ability to
properly organize user uploads in S3.
Thank you!