Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update cdn url #1123

Merged
merged 8 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const nextConfig = {
images: {
remotePatterns: [
{
hostname: "utfs.io",
pathname: "/a/s40vlb3kca/*",
hostname: "s40vlb3kca.ufs.sh",
pathname: "/f/*",
},
],
},
Expand Down
2 changes: 1 addition & 1 deletion docs/src/app/(api)/api/og/blog/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const GET = async (req: Request) => {
tw="bg-zinc-900 h-full w-full flex flex-col p-14"
style={{
backgroundImage:
"url(https://utfs.io/f/656e69ef-2800-45fd-87ac-b9f88346348c-hi270o.png)",
"url(https://s40vlb3kca.ufs.sh/f/656e69ef-2800-45fd-87ac-b9f88346348c-hi270o.png)",
backgroundPosition: "cover",
}}
>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/app/(api)/api/og/docs/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const GET = async (req: Request) => {
tw="bg-zinc-900 h-full w-full flex flex-col p-14"
style={{
backgroundImage:
"url(https://utfs.io/f/656e69ef-2800-45fd-87ac-b9f88346348c-hi270o.png)",
"url(https://s40vlb3kca.ufs.sh/f/656e69ef-2800-45fd-87ac-b9f88346348c-hi270o.png)",
backgroundPosition: "cover",
}}
>
Expand Down
5 changes: 3 additions & 2 deletions docs/src/app/(docs)/concepts/regions-acl/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ you can select the region you want to upload your files to. Once changed, all
## Access Controls

By default every file uploaded to UploadThing is accessible simply by it's URL
(`utfs.io/f/FILE_KEY`). Although this hard-to-guess URL is fine for many
applications, some applications require a more secure way to store their files.
(`<APP_ID>.ufs.sh/f/<FILE_KEY>`). Although this hard-to-guess URL is fine for
many applications, some applications require a more secure way to store their
files.

You can configure your app's access control list (ACL) to restrict access to
your files. UploadThing currently supports two different ACLs:
Expand Down
41 changes: 18 additions & 23 deletions docs/src/app/(docs)/working-with-files/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,28 @@ export const metadata = docsMetadata({
After your files have been uploaded, you will most likely want to do something
with them. This page shows how to work with your uploaded files.

## Accessing Files
## Accessing Public Files

<Warning>
Do not use the raw file URL from the storage provider, e.g. `https://bucket.s3.region.amazonaws.com/<FILE_KEY>`. We reserve the right to move objects between different storage providers and/or buckets, so this URL is not guaranteed to remain valid.
</Warning>
UploadThing serves all files from a CDN at the following URL pattern:

There are multiple ways to access your files. The most generic way is to
construct the URL from the `fileKey` you get back after the file has been
uploaded:
`https://<APP_ID>.ufs.sh/f/<FILE_KEY>`

`https://utfs.io/f/<FILE_KEY>`
If you set a `customId` when uploading the file, you can also use
`https://<APP_ID>.ufs.sh/f/<CUSTOM_ID>` to access it.

This URL will always work for public files and is the default URL returned by
the API and from any SDK method. However, sometimes you may want a URL that's
scoped to your application, for example when doing image optimizations and want
to filter what URLs are allowed to be optimized on your server. For this, the
following URL can be used:
<Warning>
Do not use the raw file URL from the storage provider, e.g. `https://bucket.s3.region.amazonaws.com/<FILE_KEY>`. We reserve the right to move objects between different storage providers and/or buckets, so this URL is not guaranteed to remain valid.
</Warning>

`https://utfs.io/a/<APP_ID>/<FILE_KEY>`
<Note>
Previously, all files were served from `https://utfs.io/f/<FILE_KEY>`.
This is still supported, but not recommended and may be deprecated in the future.
</Note>

By using this URL pattern, you have more granular control over what URLs are
allowed to be optimized. Below is an example of how to setup image optimization
allow filtering in Next.js:
Given that all files are served from a subdomain of your app, you have granular
control over what URLs are allowed to be processed. Below is an example of how
to setup image optimization allow filtering in Next.js that only allows
optimizing images from your app:

```js
/** @type {import('next').NextConfig} */
Expand All @@ -43,18 +42,14 @@ export default {
remotePatterns: [
{
protocol: "https",
hostname: "utfs.io",
pathname: "/a/<APP_ID>/*",
hostname: "<APP_ID>.ufs.sh",
pathname: "/f/*",
},
],
},
};
```

<Note>
If you set a `customId` when uploading the file, you can also use `https://utfs.io/a/<APP_ID>/<CUSTOM_ID>`.
</Note>

## Accessing Private Files

If your files are protected with
Expand Down
3 changes: 2 additions & 1 deletion examples/minimal-expo/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Go to https://uploadthing.com/dashboard to get your token
UPLOADTHING_TOKEN='...'
UPLOADTHING_TOKEN='...'
EXPO_PUBLIC_UPLOADTHING_APP_ID='...'
2 changes: 1 addition & 1 deletion examples/minimal-expo/app/f/[key].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { isImage } from "~/lib/utils";
export default function FileScreen() {
const searchParams = useGlobalSearchParams<{ key: string; name?: string }>();
const { key, name = "Untitled" } = searchParams;
const fileUrl = `https://utfs.io/f/${key}`;
const fileUrl = `https://${process.env.EXPO_PUBLIC_UPLOADTHING_APP_ID}.ufs.sh/f/${key}`;

return (
<>
Expand Down
2 changes: 1 addition & 1 deletion packages/react/test/upload-button.browser.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const worker = setupWorker(
http.all<{ key: string }>(
"https://fra1.ingest.uploadthing.com/:key",
({ params }) => {
return HttpResponse.json({ url: "https://utfs.io/f/" + params.key });
return HttpResponse.json({ url: "https://app-1.ufs.sh/f/" + params.key });
},
),
);
Expand Down
2 changes: 1 addition & 1 deletion packages/react/test/upload-dropzone.browser.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const worker = setupWorker(
http.all<{ key: string }>(
"https://fra1.ingest.uploadthing.com/:key",
({ params }) => {
return HttpResponse.json({ url: "https://utfs.io/f/" + params.key });
return HttpResponse.json({ url: "https://app-1.ufs.sh/f/" + params.key });
},
),
);
Expand Down
5 changes: 5 additions & 0 deletions packages/uploadthing/src/_internal/shared-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ export class UploadedFileData extends FileUploadDataWithCustomId.extend<Uploaded
)({
key: S.String,
url: S.String,
/**
* @deprecated
* This field is now an alias for `url`.
* This field will be removed in uploadthing v9.
*/
appUrl: S.String,
fileHash: S.String,
}) {}
Expand Down
5 changes: 5 additions & 0 deletions packages/uploadthing/src/_internal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ export type UTEvents = {
*/
export type UploadPutResult<TServerOutput = unknown> = {
url: string;
/**
* @deprecated
* This field is now an alias for `url`.
* This field will be removed in uploadthing v9.
*/
juliusmarminge marked this conversation as resolved.
Show resolved Hide resolved
appUrl: string;
fileHash: string;
serverData: TServerOutput;
Expand Down
19 changes: 9 additions & 10 deletions packages/uploadthing/test/__test-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,17 @@ export const API_URL =
typeof process !== "undefined" && process.env.UPLOADTHING_API_URL
? process.env.UPLOADTHING_API_URL
: "https://api.uploadthing.com";
export const UTFS_IO_URL =
export const UFS_HOST =
typeof process !== "undefined" && process.env.UPLOADTHING_API_URL
? "https://staging.utfs.io"
: "https://utfs.io";
? "utf-staging.com"
: "ufs.sh";
export const INGEST_URL =
typeof process !== "undefined" && process.env.UPLOADTHING_API_URL
? "https://fra1.ingest.ut-staging.com"
: "https://fra1.ingest.uploadthing.com";

export const fileUrlPattern = new RegExp(`^${UTFS_IO_URL}/f/.+$`);
export const appUrlPattern = (appId = testToken.decoded.appId) =>
new RegExp(`^${UTFS_IO_URL}/a/${appId}/.+$`);
export const fileUrlPattern = (appId = testToken.decoded.appId) =>
new RegExp(`^https://${appId}.${UFS_HOST}/f/.+$`);

export const createApiUrl = (slug: string, action?: typeof ActionType.Type) => {
const url = new URL("http://localhost:3000");
Expand Down Expand Up @@ -86,7 +85,7 @@ export const handlers = [
await callRequestSpy(request);
return HttpResponse.text("Lorem ipsum doler sit amet");
}),
http.get(`${UTFS_IO_URL}/f/:key`, async ({ request }) => {
http.get(`https://(.+).${UFS_HOST}/f/:key`, async ({ request }) => {
await callRequestSpy(request);
return HttpResponse.text("Lorem ipsum doler sit amet");
}),
Expand All @@ -99,8 +98,8 @@ export const handlers = [
await callRequestSpy(request);
const appId = new URLSearchParams(request.url).get("x-ut-identifier");
return HttpResponse.json<UploadPutResult>({
url: `${UTFS_IO_URL}/f/${params.key}`,
appUrl: `${UTFS_IO_URL}/a/${appId}/${params.key}`,
url: `https://${appId}.${UFS_HOST}/f/${params.key}`,
appUrl: `https://${appId}.${UFS_HOST}/f/${params.key}`,
serverData: null,
fileHash: Array.from(new Uint8Array(await request.arrayBuffer()))
.map((b) => b.toString(16).padStart(2, "0"))
Expand All @@ -114,7 +113,7 @@ export const handlers = [
http.post(`${API_URL}/v6/requestFileAccess`, async ({ request }) => {
await callRequestSpy(request);
return HttpResponse.json({
url: `${UTFS_IO_URL}/f/someFileKey?x-some-amz=query-param`,
url: `https://{APP_ID}.${UFS_HOST}/f/someFileKey?x-some-amz=query-param`,
});
}),
http.post(`${API_URL}/v6/updateACL`, async ({ request }) => {
Expand Down
15 changes: 7 additions & 8 deletions packages/uploadthing/test/client.browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import type {
GenerateUploaderOptions,
} from "../src/types";
import {
appUrlPattern,
doNotExecute,
fileUrlPattern,
handlers,
Expand Down Expand Up @@ -141,8 +140,8 @@ describe("uploadFiles", () => {
serverData: null,
lastModified: expect.any(Number),
key: expect.stringMatching(/.+/),
url: expect.stringMatching(fileUrlPattern),
appUrl: expect.stringMatching(appUrlPattern()),
url: expect.stringMatching(fileUrlPattern()),
appUrl: expect.stringMatching(fileUrlPattern()),
fileHash: expect.any(String),
},
]);
Expand Down Expand Up @@ -185,8 +184,8 @@ describe("uploadFiles", () => {
serverData: null,
lastModified: expect.any(Number),
key: expect.stringMatching(/.+/),
url: expect.stringMatching(fileUrlPattern),
appUrl: expect.stringMatching(appUrlPattern()),
url: expect.stringMatching(fileUrlPattern()),
appUrl: expect.stringMatching(fileUrlPattern()),
fileHash: expect.any(String),
},
]);
Expand Down Expand Up @@ -220,8 +219,8 @@ describe("uploadFiles", () => {
serverData: null,
lastModified: expect.any(Number),
key: expect.stringMatching(/.+/),
url: expect.stringMatching(fileUrlPattern),
appUrl: expect.stringMatching(appUrlPattern()),
url: expect.stringMatching(fileUrlPattern()),
appUrl: expect.stringMatching(fileUrlPattern()),
fileHash: expect.any(String),
},
]);
Expand Down Expand Up @@ -268,7 +267,7 @@ describe("uploadFiles", () => {
// customId: null,
// serverData: null,
// key: "abc-123.txt",
// url: "https://utfs.io/f/abc-123.txt",
// url: "https://app-1.ufs.sh/f/abc-123.txt",
// },
// ]);
// expect(onErrorMock).not.toHaveBeenCalled();
Expand Down
17 changes: 9 additions & 8 deletions packages/uploadthing/test/request-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
middlewareMock,
requestSpy,
testToken,
UFS_HOST,
uploadCompleteMock,
} from "./__test-helpers";

Expand Down Expand Up @@ -409,8 +410,8 @@ describe(".onUploadComplete()", () => {
status: "uploaded",
metadata: {},
file: new UploadedFileData({
url: "https://utfs.io/f/some-random-key.png",
appUrl: `https://utfs.io/a/${testToken.decoded.appId}/some-random-key.png`,
url: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
appUrl: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
name: "foo.png",
key: "some-random-key.png",
size: 48,
Expand Down Expand Up @@ -446,8 +447,8 @@ describe(".onUploadComplete()", () => {
name: "foo.png",
size: 48,
type: "image/png",
url: "https://utfs.io/f/some-random-key.png",
appUrl: `https://utfs.io/a/${testToken.decoded.appId}/some-random-key.png`,
url: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
appUrl: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
fileHash: "some-md5-hash",
},
metadata: {},
Expand All @@ -459,8 +460,8 @@ describe(".onUploadComplete()", () => {
status: "uploaded",
metadata: {},
file: new UploadedFileData({
url: "https://utfs.io/f/some-random-key.png",
appUrl: `https://utfs.io/a/${testToken.decoded.appId}/some-random-key.png`,
url: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
appUrl: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
name: "foo.png",
key: "some-random-key.png",
size: 48,
Expand Down Expand Up @@ -492,8 +493,8 @@ describe(".onUploadComplete()", () => {
status: "uploaded",
metadata: {},
file: new UploadedFileData({
url: "https://utfs.io/f/some-random-key.png",
appUrl: `https://utfs.io/a/${testToken.decoded.appId}/some-random-key.png`,
url: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
appUrl: `https://${testToken.decoded.appId}.${UFS_HOST}/f/some-random-key.png`,
name: "foo.png",
key: "some-random-key.png",
size: 48,
Expand Down
Loading
Loading