Coder Social home page Coder Social logo

syumai / workers Goto Github PK

View Code? Open in Web Editor NEW
535.0 9.0 35.0 325 KB

Go package to run an HTTP server on Cloudflare Workers.

License: MIT License

Go 62.38% Makefile 2.73% JavaScript 34.03% HTML 0.47% Shell 0.38%
cloudflare cloudflare-workers go golang

workers's Introduction

workers

Go Reference Discord Server

  • workers is a package to run an HTTP server written in Go on Cloudflare Workers.
  • This package can easily serve http.Handler on Cloudflare Workers.
  • Caution: This is an experimental project.

Features

  • serve http.Handler
  • R2
    • Head
    • Get
    • Put
    • Delete
    • List
    • Options for R2 methods
  • KV
    • Get
    • List
    • Put
    • Delete
    • Options for KV methods
  • Cache API
  • Durable Objects
    • Calling stubs
  • D1 (alpha)
  • Environment variables
  • FetchEvent
  • Cron Triggers
  • TCP Sockets

Installation

go get github.com/syumai/workers

Usage

implement your http.Handler and give it to workers.Serve().

func main() {
	var handler http.HandlerFunc = func (w http.ResponseWriter, req *http.Request) { ... }
	workers.Serve(handler)
}

or just call http.Handle and http.HandleFunc, then invoke workers.Serve() with nil.

func main() {
	http.HandleFunc("/hello", func (w http.ResponseWriter, req *http.Request) { ... })
	workers.Serve(nil) // if nil is given, http.DefaultServeMux is used.
}

For concrete examples, see _examples directory. Currently, all examples use tinygo instead of Go due to binary size issues.

Quick Start

First, please install the following tools:

  • Node.js (and npm)
  • wrangler
    • You can install it by running npm install -g wrangler.
  • tinygo 0.29.0 or later
  • gonew
    • You can install it by running go install golang.org/x/tools/cmd/gonew@latest

After installation, please run the following commands.

gonew github.com/syumai/workers/_templates/cloudflare/worker-tinygo your.module/my-app # e.g. github.com/syumai/my-app
cd my-app
go mod tidy
make dev # start running dev server
curl http://localhost:8787/hello # outputs "Hello!"

If you want a more detailed description, please refer to the README.md file in the generated directory.

FAQ

How do I deploy a worker implemented in this package?

To deploy a Worker, the following steps are required.

  • Create a worker project using wrangler.
  • Build a Wasm binary.
  • Upload a Wasm binary with a JavaScript code to load and instantiate Wasm (for entry point).

The worker-tinygo template contains all the required files, so I recommend using this template.

The worker-go template (using regular Go, not tinygo) is also available, but it requires a paid plan of Cloudflare Workers (due to the large binary size).

Where can I have discussions about contributions, or ask questions about how to use the library?

You can do both through GitHub Issues. If you want to have a more casual conversation, please use the Discord server.

workers's People

Contributors

akarasz avatar aki-0421 avatar elee1766 avatar enricodk avatar erkkah avatar minoritea avatar so-heil avatar syumai avatar zztkm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

workers's Issues

fetching a binary file returns a corrupted body

Hi! I'm using the fetch.NewRequest to build a proxy and serve files from a remote server, but non-text files are getting corrupted. The logs show the following warning:

Called .text() on an HTTP body which does not appear to be text. The body's Content-Type is "image/png". The result will probably be corrupted. Consider checking the Content-Type header before interpreting entities as text.

I was able to make it work by implementing my own toResponse function where I read the data from the blob.

Write Durable Objects in Go

Hi,

First of all, I'd like to express my thanks and my encouragement for the folks behind this project. I think this deserve full support from Cloudflare.

Now, I seem to have noticed that the Durable Objects can only be written in JS. I'd like to know if there is a plan to support writing actual DurableObject classes using Go itself, and not just the ability to call the stub from Go.

Thank you.

Error: write EPIPE when using wrangler dev to run cloudflare worker using itty-router

Issue

When I do what the quick start says, I get the following error when I run make dev

My Environment

  • Ubuntu 22.04.2 LTS (GNU/Linux 5.15.90.1-microsoft-standard-WSL2 x86_64)

Error

❯ make dev
wrangler dev
 ⛅️ wrangler 3.0.1
------------------
wrangler dev now uses local mode by default, powered by 🔥 Miniflare and 👷 workerd.
To run an edge preview session for your Worker, use wrangler dev --remote
Running custom build: make build
make[1]: Entering directory '/home/zztkm/dev/github.com/pistachiostudio/hello-api'
go run github.com/syumai/workers/cmd/workers-assets-gen@latest
tinygo build -o ./build/app.wasm -target wasm ./...
make[1]: Leaving directory '/home/zztkm/dev/github.com/pistachiostudio/hello-api'
⎔ Starting local server...
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ [b] open a browser, [d] open Devtools, [l] turn off local mode, [c] clear console, [x] to exit                                                                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:30632
            throw a;
            ^

Error: write EPIPE
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:917:11)
    at Socket._write (node:net:929:8)
    at writeOrBuffer (node:internal/streams/writable:392:12)
    at _write (node:internal/streams/writable:333:10)
    at Writable.write (node:internal/streams/writable:337:10)
    at Runtime.updateConfig (/usr/local/lib/node_modules/wrangler/node_modules/miniflare/dist/src/index.js:5120:26)
    at async #assembleAndUpdateConfig (/usr/local/lib/node_modules/wrangler/node_modules/miniflare/dist/src/index.js:9130:23)
    at async #init (/usr/local/lib/node_modules/wrangler/node_modules/miniflare/dist/src/index.js:8894:5)
Emitted 'error' event on Socket instance at:
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -32,
  code: 'EPIPE',
  syscall: 'write'
}

Node.js v18.12.1
make: *** [Makefile:3: dev] Error 7

Solution

I was able to solve the problem by installing libc++1.

apt install libc++1

refs: https://stackoverflow.com/questions/76281931/error-write-epipe-when-using-wrangler-dev-to-run-cloudflare-worker-using-itty-r

Error deploying with Terraform

I'm trying to get this (Very helpful! Thank you!) package to integrate with a Terraform workflow, instead of deploying using wrangler publish.

Here's what I've managed to get so far:

resource "terraform_data" "build" {
  # Changes to *.go files requires re-building it.
  input = {
    # https://stackoverflow.com/questions/51138667/can-terraform-watch-a-directory-for-changes
    dir_sha1 = sha1(join("", [for f in fileset("${path.module}", "*.go") : filesha1("${path.module}/${f}")]))
  }

  provisioner "local-exec" {
    command = <<EOC
go run github.com/syumai/workers/cmd/[email protected] -mode=go
GOOS=js GOARCH=wasm go build -o ./build/app.wasm .
EOC
  }
}

resource "cloudflare_worker_script" "script" {
  depends_on = [terraform_data.build]
  account_id = var.cloudflare_account_id
  name       = var.name
  content    = file("${path.module}/build/worker.mjs")

  // │ Error: error creating worker script: Wasm and blob bindings are not supported with modules; use imports instead (10021)
  module = false

  webassembly_binding {
    name   = "WASM"
    module = filebase64("./build/app.wasm")
  }
}

Refs:

This basically says "run the script to build app.wasm, then deploy the worker script with it as a binding". There's some quirks I still need to work out with TF lifecycle to ensure it builds before trying to take the filebase64, but that's not the bug I'm currently hitting.

The bug I'm hitting is that, whether or not I use the local-exec trick, deploying the script fails with:

╷
│ Error: error creating worker script: Uncaught SyntaxError: Cannot use import statement outside a module
│   at worker.js:1
│  (10021)
│ 
│   with cloudflare_worker_script.script,
│   on main.tf line 18, in resource "cloudflare_worker_script" "script":
│   18: resource "cloudflare_worker_script" "script" {
│ 

Digging around, it might be the case that the TF provider just doesn't support WASM workers, even though it claims to: cloudflare/terraform-provider-cloudflare#2039

I guess I'm opening this in case anybody's gotten this to work with this package, or understands the error message well enough to give any hints about what might be happening.

JavaScript error: The 'credentials' field on 'RequestInitializerDict' is not implemented."

Hi @syumai , Thank you for building this great repository!

I try to deploy this tool to Cloudflare Pages.

When I want to deploy my repository into pages, I got this issue JavaScript error: The 'credentials' field on 'RequestInitializerDict' is not implemented." in my local and remote pages ENV.

I search this error, like this issue, seems the Cloudflare Workers add the credentials automatically, Do you know how to disable it? Or can we manually deploy it to pages without use wrangler.

Can you help to check it? Thank you!

Cannot build wasm binary

using template

$ make dev
wrangler dev
 ⛅️ wrangler 2.1.15 (update available 2.2.1)
------------------------------------------------------
Running custom build: make build
make[1]: Entering directory '/home/arman/Go-Workspace/rapidapi-translate'
mkdir -p dist
tinygo build -o ./dist/app.wasm -target wasm ./...
# encoding/xml
/usr/lib/go-1.19/src/encoding/xml/typeinfo.go:318:14: typ.FieldByIndex undefined (type reflect.Type has no field or method FieldByIndex)
/usr/lib/go-1.19/src/encoding/xml/typeinfo.go:319:14: typ.FieldByIndex undefined (type reflect.Type has no field or method FieldByIndex)
make[1]: *** [Makefile:8: build] Error 1
make[1]: Leaving directory '/home/arman/Go-Workspace/rapidapi-translate'

✘ [ERROR] Command failed with exit code 2: make build


If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose
make: *** [Makefile:3: dev] Error 1

Remove dependencies on Context

#84 introduced new internal feature, jsutil.RuntimeContext.
This feature allows most Context-dependent functions to be fixed as follows.

Before

func Getenv(ctx context.Context, name string) string

After

func Getenv(name string) string

The change adds flexibility to Go programs using workers.

This will be breaking change.

Unable to get accurate date/time

When getting the current time with time.Now() we get back incorrect time. I assume this is because tinygo isn't accessing the system clock properly.

Could it be possible to have some function which gets the date and time from the JavaScript side of things?

Using "html/template"

Hi
I try to use templates, but got error
Is this supported ?
Thanks

import (
	...
	"html/template"
)

func main() {
	http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
		tmpl, _ := template.New("foo").Parse(`<div>{{.CounterValue}}</div>`)

		data := map[string]int{
			"CounterValue": 10,
		}
		_ = tmpl.ExecuteTemplate(w, "foo", data)
	})
	workers.Serve(nil)
}

2024-01-20 122112

Frequent "Promise will never complete" and "call to released function" errors in the fetch example

Hey.
I'm running the fetch example (_examples/fetch/main.go) under a free worker plan. When making about 2-3 requests per second the example works quite well, however, when the request rate increases to about 5 request per second the example starts to run into these errors:

...
GET https://first.hzgl.workers.dev/fetchexample - Ok @ 5/20/2023, 6:03:26 PM
GET https://first.hzgl.workers.dev/fetchexample - Exception Thrown @ 5/20/2023, 6:03:26 PM
✘ [ERROR]   Error: The script will never generate a response.
GET https://first.hzgl.workers.dev/fetchexample - Exception Thrown @ 5/20/2023, 6:03:26 PM
  (error) call to released function
✘ [ERROR]   Error: Promise will never complete.
GET https://first.hzgl.workers.dev/fetchexample - Ok @ 5/20/2023, 6:03:26 PM
...

Can fetch pkg support streaming?

When requesting a large file, it will cause err: failed on promise: TypeError: Memory limit would be exceeded before EOF.

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		fetchReq, err := fetch.NewRequest(req.Context(), http.MethodGet, "http://lg.hkg.hosthatch.com/1GB.test", nil)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		resp, err := fetch.NewClient().Do(fetchReq, nil)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintf(w, "err: %v", err)
			return
		}
		defer resp.Body.Close()
		io.Copy(w, resp.Body)
	})
	workers.Serve(nil)
}

Fresh worker-go project not working

Description

I created a fresh new project with Golang. I followed the guide https://github.com/syumai/workers/tree/main/_templates/cloudflare/worker-go#getting-started-1. Make dev and make build command are executed without any errors, but when I try to acces the localhost, where the worker is hosted, I get an error.
WebAssembly.Instance(): Import #0 module="gojs": module is not an object or function.

image

Versions

  • Go: 1.21.1
  • Node: 20.8.0 (even though I tried v16 and v18)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.