Hi there. I am trying to upload a partial url to Cloudflare stream with a next.js app(app router)
I am following this guide to proceed.
Here is my api endpoint to create a unique upload url;
// path: api/cloudflare
export async function POST(request: NextRequest) {
try {
const { CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN } = process.env;
const endpoint = `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/stream?direct_user=true`;
const headers: HeadersInit = {
Authorization: `bearer ${CLOUDFLARE_API_TOKEN}`,
"Tus-Resumable": "1.0.0",
"Upload-Length": request.headers.get("Upload-Length") || "",
"Upload-Metadata": request.headers.get("Upload-Metadata") || "",
};
const res = await fetch(endpoint, {
method: "POST",
headers,
});
if (!res.status.toString().startsWith("2")) {
const data = await res.json();
const error = data?.errors?.map((i: any) => i.message).join(",");
const message =
data?.messages?.map((i: any) => i.message).join(",") || res.statusText;
return new NextResponse(
JSON.stringify({ message: `${error} /n ${message}` }),
{
status: res.status,
headers: {
"Content-Type": "application/json",
},
}
);
}
const destination = res.headers.get("Location");
if (!destination) {
throw new Error("No destination header found");
}
return new NextResponse(JSON.stringify({ message: "success" }), {
status: res.status,
headers: {
"Access-Control-Expose-Headers": "Location",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Origin": "*",
Location: destination,
},
});
} catch (error: any) {
return new NextResponse(JSON.stringify({ message: error.message }), {
status: 500,
headers: {
"Content-Type": "application/json",
},
});
}
}
And here is my tus client implementation:
const startUpload = () => {
if (fileInputRef.current && fileInputRef.current.files) {
const file = fileInputRef.current.files[0];
if (!file) return;
const endpoint = "/api/cloudflare"; // this is pointing my api endpoint url
const chunkSize = chunkSizeInputRef.current
? parseInt(chunkSizeInputRef.current?.value || "", 10) || Infinity
: 50 * 1024 * 1024;
const parallelUploads =
parseInt(parallelUploadsInputRef.current?.value || "", 10) || 1;
var mediaId = "";
const options: tus.UploadOptions = {
endpoint,
chunkSize: chunkSize,
parallelUploads: parallelUploads,
retryDelays: [0, 1000, 3000, 5000],
metadata: {
filename: file.name,
filetype: file.type,
},
onError: (error) => {
setErrorMessage(error.message);
reset();
},
onProgress: (bytesUploaded, bytesTotal) => {
const percentage = (bytesUploaded / bytesTotal) * 100;
setUploadProgress(percentage);
},
// onBeforeRequest: function (req) {
// const xhr = req.getUnderlyingObject();
// xhr.withCredentials = true;
// },
onAfterResponse: function (req, res) {
return new Promise((resolve) => {
var mediaIdHeader = res.getHeader("stream-media-id");
if (mediaIdHeader) {
mediaId = mediaIdHeader;
}
console.log(mediaId);
resolve();
});
},
// onUploadUrlAvailable: function () {
// console.log("Upload url is available");
// },
onShouldRetry: function (err, retryAttempt, options) {
console.log("Error", err);
console.log("Request", err.originalRequest);
console.log("Response", err.originalResponse);
var status = err.originalResponse
? err.originalResponse.getStatus()
: 0;
// Do not retry if the status is a 403.
if (status === 403) {
return false;
}
// For any other status code, we retry.
return false;
},
};
const newUpload = new tus.Upload(file, options);
newUpload.start();
setUpload(newUpload);
setUploadIsRunning(true);
}
};
When I try to upload, the request to the api succeeds and do return an upload url like https://upload.videodelivery.net/tus/85bd71e39da1a1f79a56442102609781?tusv2=true
But then I get the following error;
As it is seen in the network tab, the backend enpoint to create uri succeeds but somehow tus client fails to upload the image to the given url.
I even deploy it to prevent any errors of ssl issue at THIS SITE
You can also check it out from there and inspect the console for any ideas.
I really got stuck with this problem and have been struggling to solve it for the last one week.
Any help will be appreciated.