split r2-image-viewer example

This commit is contained in:
syumai 2022-05-29 11:22:24 +09:00
parent dd44ee2c0d
commit d865a1e67d
8 changed files with 140 additions and 1 deletions

View File

@ -0,0 +1,12 @@
.PHONY: dev
dev:
wrangler dev
.PHONY: build
build:
mkdir -p dist
tinygo build -o ./dist/app.wasm -target wasm ./...
.PHONY: publish
publish:
wrangler publish

View File

@ -0,0 +1,33 @@
# r2-image-viewer-tinygo
* An example server which returns image from Cloudflare R2.
* This server is implemented in Go and compiled with tinygo.
## Example
* https://r2-image-viewer-tinygo.syumai.workers.dev/syumai.png
## Development
### Requirements
This project requires these tools to be installed globally.
* wrangler
* tinygo
### Commands
```
make dev # run dev server
make build # build Go Wasm binary
make publish # publish worker
```
## Author
syumai
## License
MIT

View File

@ -0,0 +1,7 @@
module github.com/syumai/workers/examples/r2-image-viewer-tinygo
go 1.18
require github.com/syumai/workers v0.0.0-00010101000000-000000000000
replace github.com/syumai/workers => ../../

View File

View File

@ -0,0 +1,53 @@
package main
import (
"fmt"
"io"
"log"
"net/http"
"strings"
"github.com/syumai/workers"
)
// bucketName is R2 bucket name defined in wrangler.toml.
const bucketName = "BUCKET"
func handleErr(w http.ResponseWriter, msg string, err error) {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(msg))
}
// This example is based on implementation in syumai/workers-playground
// * https://github.com/syumai/workers-playground/blob/e32881648ccc055e3690a0d9c750a834261c333e/r2-image-viewer/src/index.ts#L30
func handler(w http.ResponseWriter, req *http.Request) {
bucket, err := workers.NewR2Bucket(bucketName)
if err != nil {
handleErr(w, "failed to get R2Bucket\n", err)
return
}
imgPath := strings.TrimPrefix(req.URL.Path, "/")
imgObj, err := bucket.Get(imgPath)
if err != nil {
handleErr(w, "failed to get R2Object\n", err)
return
}
if imgObj == nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(fmt.Sprintf("image not found: %s", imgPath)))
return
}
w.Header().Set("Cache-Control", "public, max-age=14400")
w.Header().Set("ETag", fmt.Sprintf("W/%s", imgObj.HTTPETag))
contentType := "application/octet-stream"
if imgObj.HTTPMetadata.ContentType != "" {
contentType = imgObj.HTTPMetadata.ContentType
}
w.Header().Set("Content-Type", contentType)
io.Copy(w, imgObj.Body)
}
func main() {
workers.Serve(http.HandlerFunc(handler))
}

View File

@ -0,0 +1,20 @@
import "../assets/polyfill_performance.js";
import "../assets/wasm_exec.js";
import mod from "./dist/app.wasm";
const go = new Go();
const load = WebAssembly.instantiate(mod, go.importObject).then((instance) => {
go.run(instance);
return instance;
});
async function processRequest(event) {
const req = event.request;
await load;
return handleRequest(req);
}
addEventListener("fetch", (event) => {
event.respondWith(processRequest(event));
})

View File

@ -0,0 +1,14 @@
name = "r2-image-viewer-tinygo"
main = "./worker.mjs"
compatibility_date = "2022-05-13"
compatibility_flags = [
"streams_enable_constructors"
]
[build]
command = "make build"
[[r2_buckets]]
binding = 'BUCKET'
bucket_name = 'r2-image-viewer'
preview_bucket_name = 'r2-image-viewer-dev'

View File

@ -25,7 +25,7 @@ var _ R2Bucket = &r2Bucket{}
// NewR2Bucket returns R2Bucket for given variable name.
// * variable name must be defined in wrangler.toml.
// - see example: https://github.com/syumai/workers/tree/main/examples/r2-image-server
// - see example: https://github.com/syumai/workers/tree/main/examples/r2-image-viewer
// * if the given variable name doesn't exist on global object, returns error.
func NewR2Bucket(varName string) (R2Bucket, error) {
inst := js.Global().Get(varName)