|
1 | | -//go:build js && wasm |
| 1 | +//go:build !js |
2 | 2 |
|
3 | 3 | package workers |
4 | 4 |
|
5 | 5 | import ( |
6 | | - "context" |
7 | 6 | "fmt" |
8 | | - "io" |
9 | 7 | "net/http" |
10 | | - "syscall/js" |
11 | | - |
12 | | - "github.com/syumai/workers/internal/jshttp" |
13 | | - "github.com/syumai/workers/internal/jsutil" |
14 | | - "github.com/syumai/workers/internal/runtimecontext" |
15 | | -) |
16 | | - |
17 | | -var ( |
18 | | - httpHandler http.Handler |
19 | | - closeCh = make(chan struct{}) |
| 8 | + "os" |
20 | 9 | ) |
21 | 10 |
|
22 | | -func init() { |
23 | | - var handleRequestCallback js.Func |
24 | | - handleRequestCallback = js.FuncOf(func(this js.Value, args []js.Value) any { |
25 | | - reqObj := args[0] |
26 | | - var cb js.Func |
27 | | - cb = js.FuncOf(func(_ js.Value, pArgs []js.Value) any { |
28 | | - defer cb.Release() |
29 | | - resolve := pArgs[0] |
30 | | - reject := pArgs[1] |
31 | | - go func() { |
32 | | - if len(args) > 1 { |
33 | | - reject.Invoke(jsutil.Errorf("too many args given to handleRequest: %d", len(args))) |
34 | | - return |
35 | | - } |
36 | | - res, err := handleRequest(reqObj) |
37 | | - if err != nil { |
38 | | - reject.Invoke(jsutil.Error(err.Error())) |
39 | | - return |
40 | | - } |
41 | | - resolve.Invoke(res) |
42 | | - }() |
43 | | - return js.Undefined() |
44 | | - }) |
45 | | - return jsutil.NewPromise(cb) |
46 | | - }) |
47 | | - jsutil.Binding.Set("handleRequest", handleRequestCallback) |
48 | | -} |
49 | | - |
50 | | -type appCloser struct { |
51 | | - io.ReadCloser |
52 | | -} |
53 | | - |
54 | | -func (c *appCloser) Close() error { |
55 | | - defer close(closeCh) |
56 | | - return c.ReadCloser.Close() |
57 | | -} |
58 | | - |
59 | | -// handleRequest accepts a Request object and returns Response object. |
60 | | -func handleRequest(reqObj js.Value) (js.Value, error) { |
61 | | - if httpHandler == nil { |
62 | | - return js.Value{}, fmt.Errorf("Serve must be called before handleRequest.") |
63 | | - } |
64 | | - req, err := jshttp.ToRequest(reqObj) |
65 | | - if err != nil { |
66 | | - return js.Value{}, err |
67 | | - } |
68 | | - ctx := runtimecontext.New(context.Background(), reqObj) |
69 | | - req = req.WithContext(ctx) |
70 | | - reader, writer := io.Pipe() |
71 | | - w := &jshttp.ResponseWriter{ |
72 | | - HeaderValue: http.Header{}, |
73 | | - StatusCode: http.StatusOK, |
74 | | - Reader: &appCloser{reader}, |
75 | | - Writer: writer, |
76 | | - ReadyCh: make(chan struct{}), |
77 | | - } |
78 | | - go func() { |
79 | | - defer w.Ready() |
80 | | - defer writer.Close() |
81 | | - httpHandler.ServeHTTP(w, req) |
82 | | - }() |
83 | | - <-w.ReadyCh |
84 | | - return w.ToJSResponse(), nil |
85 | | -} |
86 | | - |
87 | | -//go:wasmimport workers ready |
88 | | -func ready() |
89 | | - |
90 | | -// Server serves http.Handler on a JS runtime. |
| 11 | +// Server serves http.Handler as a normal HTTP server. |
91 | 12 | // if the given handler is nil, http.DefaultServeMux will be used. |
| 13 | +// As a port number, PORT environment variable or default value (9900) is used. |
| 14 | +// This function is implemented for non-JS environments for debugging purposes. |
92 | 15 | func Serve(handler http.Handler) { |
93 | 16 | if handler == nil { |
94 | 17 | handler = http.DefaultServeMux |
95 | 18 | } |
96 | | - httpHandler = handler |
97 | | - ready() |
98 | | - <-closeCh |
| 19 | + port := os.Getenv("PORT") |
| 20 | + if port == "" { |
| 21 | + port = "9900" |
| 22 | + } |
| 23 | + addr := fmt.Sprintf(":%s", port) |
| 24 | + fmt.Printf("listening on: http://localhost%s\n", addr) |
| 25 | + fmt.Fprintln(os.Stderr, "warn: this server is currently running in non-JS mode. to enable JS-related features, please use the make command in the syumai/workers template.") |
| 26 | + http.ListenAndServe(addr, handler) |
99 | 27 | } |
0 commit comments