55 "io"
66 "log"
77 "net/http"
8+ "os"
89 "strings"
910
1011 "github.com/syumai/workers"
@@ -16,26 +17,61 @@ const bucketName = "BUCKET"
1617func handleErr (w http.ResponseWriter , msg string , err error ) {
1718 log .Println (err )
1819 w .WriteHeader (http .StatusInternalServerError )
20+ w .Header ().Set ("Content-Type" , "text/plain" )
1921 w .Write ([]byte (msg ))
2022}
2123
22- // This example is based on implementation in syumai/workers-playground
23- // * https://github.com/syumai/workers-playground/blob/e32881648ccc055e3690a0d9c750a834261c333e/r2-image-viewer/src/index.ts#L30
24- func handler (w http.ResponseWriter , req * http.Request ) {
24+ type server struct {
25+ bucket workers.R2Bucket
26+ }
27+
28+ func newServer () (* server , error ) {
29+ // delete image object from R2
2530 bucket , err := workers .NewR2Bucket (bucketName )
2631 if err != nil {
27- handleErr (w , "failed to get R2Bucket\n " , err )
32+ return nil , err
33+ }
34+ return & server {bucket : bucket }, nil
35+ }
36+
37+ func (s * server ) post (w http.ResponseWriter , req * http.Request , key string ) {
38+ objects , err := s .bucket .List ()
39+ if err != nil {
40+ handleErr (w , "failed to list R2Objects\n " , err )
2841 return
2942 }
30- imgPath := strings .TrimPrefix (req .URL .Path , "/" )
31- imgObj , err := bucket .Get (imgPath )
43+ for _ , obj := range objects .Objects {
44+ if obj .Key == key {
45+ w .WriteHeader (http .StatusBadRequest )
46+ fmt .Fprintf (w , "key %s already exists\n " , key )
47+ return
48+ }
49+ }
50+ _ , err = s .bucket .Put (key , req .Body , & workers.R2PutOptions {
51+ HTTPMetadata : workers.R2HTTPMetadata {
52+ ContentType : req .Header .Get ("Content-Type" ),
53+ },
54+ CustomMetadata : map [string ]string {"custom-key" : "custom-value" },
55+ })
56+ if err != nil {
57+ handleErr (w , "failed to put R2Object\n " , err )
58+ return
59+ }
60+ w .WriteHeader (http .StatusCreated )
61+ w .Header ().Set ("Content-Type" , "text/plain" )
62+ w .Write ([]byte ("successfully uploaded image" ))
63+ }
64+
65+ func (s * server ) get (w http.ResponseWriter , req * http.Request , key string ) {
66+ // get image object from R2
67+ imgObj , err := s .bucket .Get (key )
3268 if err != nil {
3369 handleErr (w , "failed to get R2Object\n " , err )
3470 return
3571 }
3672 if imgObj == nil {
3773 w .WriteHeader (http .StatusNotFound )
38- w .Write ([]byte (fmt .Sprintf ("image not found: %s" , imgPath )))
74+ w .Write ([]byte (fmt .Sprintf ("image not found: %s" , key )))
3975 return
4076 }
4177 w .Header ().Set ("Cache-Control" , "public, max-age=14400" )
@@ -48,6 +84,40 @@ func handler(w http.ResponseWriter, req *http.Request) {
4884 io .Copy (w , imgObj .Body )
4985}
5086
87+ func (s * server ) delete (w http.ResponseWriter , req * http.Request , key string ) {
88+ // delete image object from R2
89+ if err := s .bucket .Delete (key ); err != nil {
90+ handleErr (w , "failed to delete R2Object\n " , err )
91+ return
92+ }
93+ w .Header ().Set ("Content-Type" , "text/plain" )
94+ w .Write ([]byte ("successfully deleted image" ))
95+ }
96+
97+ func (s * server ) routeHandler (w http.ResponseWriter , req * http.Request ) {
98+ key := strings .TrimPrefix (req .URL .Path , "/" )
99+ switch req .Method {
100+ case "GET" :
101+ s .get (w , req , key )
102+ return
103+ case "DELETE" :
104+ s .delete (w , req , key )
105+ return
106+ case "POST" :
107+ s .post (w , req , key )
108+ return
109+ default :
110+ w .WriteHeader (http .StatusNotFound )
111+ w .Write ([]byte ("url not found\n " ))
112+ return
113+ }
114+ }
115+
51116func main () {
52- workers .Serve (http .HandlerFunc (handler ))
117+ s , err := newServer ()
118+ if err != nil {
119+ fmt .Fprintf (os .Stderr , "failed to start server: %v" , err )
120+ os .Exit (1 )
121+ }
122+ workers .Serve (http .HandlerFunc (s .routeHandler ))
53123}
0 commit comments