sor4chi / hono-storage

A storage helper for Hono. Support disk, memory, S3, etc.
MIT License
101 stars 3 forks source link

Feature: Support to make download link easily #18

Closed Code-Hex closed 9 months ago

Code-Hex commented 10 months ago

Hi šŸ‘‹ I would like to use this library in production.

So I send a request to support making signed URLs which give time-limited access to a specific R2 resource. (Same as GCS feature one: https://cloud.google.com/storage/docs/access-control/signed-urls?hl=en)

sor4chi commented 10 months ago

Hi, @Code-Hex Thank you for requesting! I am not familiar with that function, so I apologize if I am misinterpreting it.

Surely it's useful to be able to set it up from HonoS3Storage. Iā€™d like to add this feature.

So, we have to discuss about the interface. I have two suggestion of this implementation.

1 ) Add sign field to HonoS3Storage option and recieve signedUrl with vars.

const storage = new HonoS3Storage({
  key: (_, file) => `${file.originalname}-${new Date().getTime()}`,
  bucket: "[your-bucket-name]",
  client,
  sign: {
    expireIn: 3600, // add sign field (from @aws-sdk/s3-request-presigner)
  }
});

app.get("/", storage.single("image"), (c) => c.text(c.vars.files.image.signedUrl))
app.get("/", storage.fields([
  { name: "image" },
  { name: "pdf"}
]), (c) => c.json({ 
  image: c.vars.files.image.signedUrl, // 3600
  pdf: c.vars.files.pdf.signedUrl // 3600
}))

2 ) Extend storage.single, .multiple, .fields, and enable to set sign to each field.

const storage = new HonoS3Storage({
  key: (_, file) => `${file.originalname}-${new Date().getTime()}`,
  bucket: "[your-bucket-name]",
  client,
});

app.get("/", storage.single("image", { expire: 3600 }), (c) => c.text(c.vars.files.image.signedUrl))
app.get("/", storage.fields([
  { name: "image", sign: { expireIn: 3600 }},
  { name: "pdf", sign: { expireIn: 3600 * 24 }}
]), (c) => c.json({ 
  image: c.vars.files.image.signedUrl, // 3600
  pdf: c.vars.files.pdf.signedUrl // 3600 * 24
}))

If you have any other good interfaces or suggestions for improvement, please suggest me!

Code-Hex commented 10 months ago

@sor4chi Thanks for your suggestion. I like the second opinion. because It's clear that each file is associated with an expiration date.

sor4chi commented 10 months ago

@Code-Hex Okay, then I will start with opening the custom fields in the core package! Thanks!

I plan to use @aws-sdk/s3-request-presigner internally, do you have any comments or requests regarding this? https://developers.cloudflare.com/r2/examples/aws/aws-sdk-js-v3/#generate-presigned-urls

Code-Hex commented 10 months ago

@sor4chi No I don't have! I'm looking forward to implementing this feature!

yusukebe commented 10 months ago

Hi @sor4chi and @Code-Hex,

The logic may not be the same, but I've created the "SignedRequest Middleware" in my personal repo:

https://github.com/yusukebe/signed-request-middleware

And here's a Japanese description: https://zenn.dev/yusukebe/articles/647aa9ba8c1550#11.%E3%83%9B%E3%83%83%E3%83%88%E3%83%AA%E3%83%B3%E3%82%AF%E7%A6%81%E6%AD%A2---signedrequest%E7%B7%A8

I think it would be better to make it more general and have it as built-in middleware if there's potential for it to be used by many users. What do you think? However, I'm not fully understanding the methods of GCP and AWS, so it may not be a completely related thing.

sor4chi commented 10 months ago

Hi, @yusukebe. Thank you for suggest.

It is true that it would be more generic to use middleware, but in this case, I want to set a different sign for each field and get the signedUrl at the same time as the post to R2.