- 用一张照片生成你从年幼到年老的3秒GIF动图
- 使用 Workers 从 Cloudflare R2 存储和检索照片
- 通过 Upstash 缓存24小时后自动删除照片
- NextAuth 授权,MongoDB 存储用户信息
将文件
.env.example
重命名为.env
变量 | 描述 | 示例 |
---|---|---|
REPLICATE_API_TOKEN |
replicate | fdsgsfasfadadasfasgdfhb |
UPSTASH_REDIS_REST_URL |
`https://apn1-xxx-xxx | |
.upstash.io` | ||
UPSTASH_REDIS_REST_TOKEN |
xxxxxx= |
|
QSTASH_TOKEN |
xxxxxx= |
|
QSTASH_CURRENT_SIGNING_KEY |
sig_xxxxx |
|
QSTASH_NEXT_SIGNING_KEY |
sig_xxxxx |
|
NEXT_PUBLIC_CLOUDFLARE_WORKER |
https://project.username.workers.dev |
|
CLOUDFLARE_WORKER_SECRET |
随机 token | sfhggdjhkghkgdk |
GITHUB_CLIENT_ID |
OAuth App ID | dgvsfdahdfajdfag |
GITHUB_CLIENT_SECRET |
OAuth App SECRET | fsdagfadshfdahgfasgsadg |
NEXTAUTH_SECRET |
随机 token | safadsgdsagfdgfdsgdf |
MONGODB_URI |
uri | mongodb+srv://... |
- 注册 ReplicateHQ 帐户以获取
REPLICATE_API_TOKEN
环境变量。 - 注册 Upstash 帐户以获取
Upstash Redis
和QStash
环境变量。 - 创建一个 Cloudflare R2 实例 和 Cloudflare Worker 来处理图片上传和读取(下方有详细介绍)。
Cloudflare R2 设置说明
- 在 Cloudflare 创建一个 R2存储桶(R2 bucket)。
- 使用下面的代码创建一个 Cloudflare Worker。
- 在
Settings > R2 Bucket Bindings
将您的工作程序绑定到您的R2实例。 - 为保证安全性,请在
Settings > Environment Variables
下设置AUTH_KEY_SECRET
变量(您可以在此处生成随机token)。 - 用你自己的 Cloudflare Worker 端点替换项目中的
older.yesmore.workers.dev
代码片段。
Cloudflare Worker Code:
// Check requests for a pre-shared secret
const hasValidHeader = (request, env) => {
return request.headers.get("X-CF-Secret") === env.AUTH_KEY_SECRET;
};
function authorizeRequest(request, env, key) {
switch (request.method) {
case "PUT":
case "DELETE":
return hasValidHeader(request, env);
case "GET":
return true;
default:
return false;
}
}
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
if (!authorizeRequest(request, env, key)) {
return new Response("Forbidden", { status: 403 });
}
switch (request.method) {
case "PUT":
await env.MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
case "GET":
const object = await env.MY_BUCKET.get(key);
if (object === null) {
return new Response("Object Not Found", { status: 404 });
}
const headers = new Headers();
object.writeHttpMetadata(headers);
headers.set("etag", object.httpEtag);
return new Response(object.body, {
headers,
});
case "DELETE":
await env.MY_BUCKET.delete(key);
return new Response("Deleted!");
default:
return new Response("Method Not Allowed", {
status: 405,
headers: {
Allow: "PUT, GET, DELETE",
},
});
}
},
};
then have fun~