tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/examples/net/webserver/main.go (about) 1 // This example listens on port :80 serving a web page. Multiple clients 2 // may connect and be serviced at the same time. IPv4 only. HTTP only. 3 // 4 // $ curl http://10.0.0.2 5 // 6 // Note: It may be necessary to increase the stack size when using "net/http". 7 // Use the -stack-size=4KB command line option. 8 9 //go:build ninafw || wioterminal 10 11 package main 12 13 import ( 14 "fmt" 15 "log" 16 "machine" 17 "net/http" 18 "strconv" 19 "time" 20 21 "tinygo.org/x/drivers/netlink" 22 "tinygo.org/x/drivers/netlink/probe" 23 ) 24 25 var ( 26 ssid string 27 pass string 28 port string = ":80" 29 ) 30 31 var led = machine.LED 32 33 func main() { 34 35 // wait a bit for serial 36 time.Sleep(2 * time.Second) 37 38 led.Configure(machine.PinConfig{Mode: machine.PinOutput}) 39 40 link, _ := probe.Probe() 41 42 err := link.NetConnect(&netlink.ConnectParams{ 43 Ssid: ssid, 44 Passphrase: pass, 45 }) 46 if err != nil { 47 log.Fatal(err) 48 } 49 50 http.HandleFunc("/", root) 51 http.HandleFunc("/hello", hello) 52 http.HandleFunc("/cnt", cnt) 53 http.HandleFunc("/6", sixlines) 54 http.HandleFunc("/off", LED_OFF) 55 http.HandleFunc("/on", LED_ON) 56 57 err = http.ListenAndServe(port, nil) 58 for err != nil { 59 fmt.Printf("error: %s\r\n", err.Error()) 60 time.Sleep(5 * time.Second) 61 } 62 } 63 64 func root(w http.ResponseWriter, r *http.Request) { 65 access := 1 66 67 cookie, err := r.Cookie("access") 68 if err != nil { 69 if err == http.ErrNoCookie { 70 cookie = &http.Cookie{ 71 Name: "access", 72 Value: "1", 73 } 74 } else { 75 http.Error(w, fmt.Sprintf("%s", err.Error()), http.StatusBadRequest) 76 return 77 } 78 } else { 79 v, err := strconv.ParseInt(cookie.Value, 10, 0) 80 if err != nil { 81 http.Error(w, fmt.Sprintf("invalid cookie.Value : %s", cookie.Value), http.StatusBadRequest) 82 return 83 } 84 cookie.Value = fmt.Sprintf("%d", v+1) 85 access = int(v) + 1 86 } 87 http.SetCookie(w, cookie) 88 w.WriteHeader(http.StatusOK) 89 90 fmt.Fprintf(w, ` 91 <html> 92 <head> 93 <title>TinyGo HTTP Server</title> 94 <script language="javascript" type="text/javascript"> 95 var counter = 0 96 function ledOn() { fetch("/on"); } 97 function ledOff() { fetch("/off"); } 98 function fetchCnt() { fetch("/cnt").then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); } 99 function incrCnt() { counter = counter + 1; fetch("/cnt?cnt=" + counter, { method: 'POST' }).then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); } 100 function setCnt() { fetch("/cnt", { 101 method: "POST", 102 body: "cnt=" + document.getElementsByName("cnt")[0].value, 103 headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, 104 }).then(response => response.json()).then(json => { counter = json.cnt; cnt.innerHTML = counter; }); return false; } 105 function onLoad() { fetchCnt(); } 106 </script> 107 </head> 108 <body onLoad="onLoad()"> 109 <h5>TinyGo HTTP Server</h5> 110 111 <p> 112 access: %d 113 </p> 114 115 <a href="/hello">/hello</a><br> 116 <a href="/6">/6</a><br> 117 118 <p> 119 LED<br> 120 <a href="javascript:ledOn();">/on</a><br> 121 <a href="javascript:ledOff();">/off</a><br> 122 </p> 123 124 125 <p> 126 <a href="/cnt">/cnt</a><br> 127 cnt: <span id="cnt"></span><br> 128 <a href="javascript:incrCnt()">incrCnt()</a><br> 129 <form id="form1" style="display: inline" onSubmit="return setCnt()"> 130 <input type="text" name="cnt"> 131 <input type="button" value="set cnt", onClick="setCnt()"> 132 </form> 133 </p> 134 </body> 135 </html> 136 `, access) 137 } 138 139 func sixlines(w http.ResponseWriter, r *http.Request) { 140 // https://fukuno.jig.jp/3267 141 fmt.Fprint(w, `<body onload='onkeydown=e=>K=parseInt(e.key[5]||6,28)/3-8;Z=X=[B=A=12];Y=_=>`+ 142 `{for(C=[q=c=i=4];f=i--*K;c-=!Z[h+(K+6?p+K:C[i]=p*A-(p/9|0)*145)])p=B[i];for(c?0:K+6?h+=K:B=C;`+ 143 `i=K=q--;f+=Z[A+p])X[p=h+B[q]]=1;h+=A;if(f|B)for(Z=X,X=[l=228],B=[[-7,-20,6,h=17,-9,3,3][t=++t%7]-4,0,1,t-6?-A:2];l--;)`+ 144 `for(l%A?l-=l%A*!Z[l]:(P++,c=l+=A);--c>A;)Z[c]=Z[c-A];for(S="";i<240;S+=X[i]|(X[i]=Z[i]|=++i%A<2|i>228)?i%A?"■":"■<br>":" ");`+ 145 `D.innerHTML=S+P;setTimeout(Y,i-P)};Y(h=K=t=P=0)'id=D>`) 146 } 147 148 func LED_ON(w http.ResponseWriter, r *http.Request) { 149 led.High() 150 w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`) 151 fmt.Fprintf(w, "led.High()") 152 } 153 154 func LED_OFF(w http.ResponseWriter, r *http.Request) { 155 led.Low() 156 w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`) 157 fmt.Fprintf(w, "led.Low()") 158 } 159 160 func hello(w http.ResponseWriter, r *http.Request) { 161 w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`) 162 fmt.Fprintf(w, "hello") 163 } 164 165 var counter int 166 167 func cnt(w http.ResponseWriter, r *http.Request) { 168 r.ParseForm() 169 if r.Method == "POST" { 170 c := r.Form.Get("cnt") 171 if c != "" { 172 i64, _ := strconv.ParseInt(c, 0, 0) 173 counter = int(i64) 174 } 175 } 176 177 w.Header().Set(`Content-Type`, `application/json`) 178 fmt.Fprintf(w, `{"cnt": %d}`, counter) 179 }