`generateUrl` returns insecure URL and subsequent chunk uploads fail
Closed this issue · 2 comments
Initial checklist
- I understand this is a bug report and questions should be posted in the Community Forum
- I searched issues and couldn’t find anything (or linked relevant results below)
Steps to reproduce
I'm using @tus/server with next.js pages router.
I set up my api route: pages/api/file/tus/[[...file]].ts
import type { NextApiRequest, NextApiResponse } from "next";
import slugify from "@sindresorhus/slugify";
import { S3Store } from "@tus/s3-store";
import { Server } from "@tus/server";
import { getServerSession } from "next-auth/next";
import path from "node:path";
import { newId } from "@/lib/id-helper";
import { authOptions } from "../../auth/[...nextauth]";
export const config = {
api: {
bodyParser: false,
},
};
const tusServer = new Server({
// `path` needs to match the route declared by the next file router
path: "/api/file/tus",
datastore: new S3Store({
partSize: 8 * 1024 * 1024, // each uploaded part will have ~8MiB,
s3ClientConfig: {
bucket: process.env.NEXT_PRIVATE_UPLOAD_BUCKET as string,
region: process.env.NEXT_PRIVATE_UPLOAD_REGION as string,
credentials: {
accessKeyId: process.env.NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID as string,
secretAccessKey: process.env
.NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY as string,
},
},
}),
namingFunction(req, metadata) {
const { teamId, fileName } = metadata as {
teamId: string;
fileName: string;
};
const docId = newId("doc");
const { name, ext } = path.parse(fileName);
const newName = `${teamId}/${docId}/${slugify(name)}${ext}`;
return newName;
},
generateUrl(req, { proto, host, path, id }) {
// Encode the ID to be URL safe
id = Buffer.from(id, "utf-8").toString("base64url");
return `${proto}://${host}${path}/${id}`;
},
getFileIdFromRequest(req) {
// Extract the ID from the URL
const id = (req.url as string).split("/api/file/tus/")[1];
return Buffer.from(id, "base64url").toString("utf-8");
},
});
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// Get the session
const session = getServerSession(req, res, authOptions);
if (!session) {
return res.status(401).json({ message: "Unauthorized" });
}
return tusServer.handle(req, res);
}
Everything works well if the file is less than the chunk size I specified in the tus.Upload
from tus-js-client implementation. However, if that exceeds then @tus/server generates a new URL for subsequent chunk uploads using the generateUrl
function.
For whatever reason, the proto
value returns http
instead of https
. This leads to an insecure URL and my application refuses to execute it, throwing CORS errors.
I fixed it by modifying the return statement of generateUrl
and hardcoding a s
after proto
.
...
generateUrl(req, { proto, host, path, id }) {
// Encode the ID to be URL safe
id = Buffer.from(id, "utf-8").toString("base64url");
return `${proto}s://${host}${path}/${id}`;
},
...
Expected behavior
proto should be https not http
Actual behavior
proto is http not https
Hi, you checked the checkbox indicating you searched issues and find nothing relevant. The most recent issue that was openend before yours, with almost the same title, has your answer: #634 (which in turn was a duplicate of another of the same).
Regarding chunkSize
, you should never set it on the client unless you are forced too. See the warnings in the tus-js-client docs if you're wondering why.
Thanks @Murderlon. I swear I searched the issues but must have forgotten to look in closed issues. My bad.
Regarding
chunkSize
, you should never set it on the client unless you are forced too. See the warnings in the tus-js-client docs if you're wondering why.
Yes, that's a great point. I'm deploying to a serverless infra, therefore my request body size is limited to 4.5 MB hence the chunkSize
in the tus-js-client.