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  }