commit 20f31d3d9eeb8609059d6056a159eaf18e61ed5f Author: sp Date: Fri Jul 30 23:22:08 2021 +1000 initial web server with websocket support. diff --git a/.gcloudignore b/.gcloudignore new file mode 100644 index 0000000..199e6d9 --- /dev/null +++ b/.gcloudignore @@ -0,0 +1,25 @@ +# This file specifies files that are *not* uploaded to Google Cloud Platform +# using gcloud. It follows the same syntax as .gitignore, with the addition of +# "#!include" directives (which insert the entries of the given .gitignore-style +# file at that point). +# +# For more information, run: +# $ gcloud topic gcloudignore +# +.gcloudignore +# If you would like to upload your .git directory, .gitignore file or files +# from your .gitignore file, remove the corresponding line +# below: +.git +.gitignore + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +# Test binary, build with `go test -c` +*.test +# Output of the go coverage tool, specifically when used with LiteIDE +*.out \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/goweb.iml b/.idea/goweb.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/goweb.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..5609ccc --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/api1.go b/api1.go new file mode 100644 index 0000000..13ea2ba --- /dev/null +++ b/api1.go @@ -0,0 +1,11 @@ +package main + +import ( + "net/http" +) + +const apiV1Prefix = "/api1/" + +func apiV1Main(http.ResponseWriter, *http.Request) { + +} diff --git a/api1ws.go b/api1ws.go new file mode 100644 index 0000000..aa61b4a --- /dev/null +++ b/api1ws.go @@ -0,0 +1,67 @@ +package main + +import ( + "fmt" + "github.com/gorilla/websocket" + "log" + "net/http" +) + +const apiV1WebSocket = apiV1Prefix + "ws" + +// We'll need to define an upgradeToWs +// this will require a Read and Write buffer size +var upgradeToWs = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, +} + +func apiV1WebSocketHandler(w http.ResponseWriter, r *http.Request) { + upgradeToWs.CheckOrigin = func(r *http.Request) bool { return true } + ws, err := upgradeToWs.Upgrade(w, r, nil) + if err != nil { + log.Println("cannot upgrade websocket", err) + return + } + + // helpful log statement to show connections + log.Println("Websocket Api/V1: Client Connected", r.RemoteAddr) + + wsReader(ws) +} + +func wsReader(conn *websocket.Conn) { + for { + // read in a message + messageType, p, err := conn.ReadMessage() + if err != nil { + log.Println(err) + return + } + + WsEchoIncomingMessage(conn, string(p), messageType) + //switch messageType { + //case websocket.TextMessage: + // WsProcessingTxtMessage(conn, string(p)) + // break + //case websocket.BinaryMessage: + // WsProcessingBinaryMessage(conn, p) + // break + //case websocket.PingMessage: + // break + //case websocket.PongMessage: + // break + //} + } +} + +func WsEchoIncomingMessage(conn *websocket.Conn, msg string, messageType int) { + // print out that message for clarity + fmt.Println(msg) + + // this is echo + if err := conn.WriteMessage(messageType, []byte(msg)); err != nil { + log.Println(err) + return + } +} diff --git a/app.yaml b/app.yaml new file mode 100644 index 0000000..e46078e --- /dev/null +++ b/app.yaml @@ -0,0 +1 @@ +runtime: go115 \ No newline at end of file diff --git a/config.go b/config.go new file mode 100644 index 0000000..a94fcc8 --- /dev/null +++ b/config.go @@ -0,0 +1,48 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "log" +) + +type configStaticHtml struct { + Dir string + StaticUrl string + StripPrefix string +} + +type configuration struct { + Host string + Port string + DSN string + TlsCert string + TlsKey string + Static []configStaticHtml + Debug bool + TempDir string + Session struct { //TODO: figure what is this intended for + Guest bool + Year int //how many years + Month int //how many years + Day int //how many years + } +} + +var configFile = "config.json" +var config = configuration{} + +func (m *configuration) readConfig() (e error) { + log.Printf("read Path config from %s", configFile) + body, e := ioutil.ReadFile(configFile) + if e != nil { + log.Fatal("Cannot read config from " + configFile) + return + } + e = json.Unmarshal(body, m) + + if config.Debug { + log.Println(config) + } + return +} diff --git a/config.json b/config.json new file mode 100644 index 0000000..e256aad --- /dev/null +++ b/config.json @@ -0,0 +1,31 @@ +{ + "Host":"0.0.0.0", + "Port":"8080", + "DSN": "sp:sp@tcp(192.168.1.70:3306)/syd_credit?parseTime=true&loc=Australia%2FSydney&collation=utf8mb4_0900_ai_ci", + "TlsCert": "fullchain.pem", + "TlsKey": "privkey.pem", + "Debug": true, + "Static": [ + { + "Dir": "./html/", + "StaticUrl": "/", + "StripPrefix" : "/" + }, + { + "Dir": "./html/test/", + "StaticUrl": "/spa1/", + "StripPrefix" : "/spa1/" + }, + { + "Dir": "./html/test/", + "StaticUrl": "/spa2/", + "StripPrefix" : "/spa2/" + } + ], + "Session" : { + "Guest": true, + "Year": 10, + "Month": 1, + "Day": 1 + } +} \ No newline at end of file diff --git a/html/css/index.css b/html/css/index.css new file mode 100644 index 0000000..1a87e13 --- /dev/null +++ b/html/css/index.css @@ -0,0 +1,24 @@ +p { + background-color:yellow; +} + +h1 { + text-align: center; + text-decoration: #1ABC9C; +} + +div { + width: 300px; + margin: auto; + text-align: left; +} + +hr { + width: 100px; + border: 10px solid green; + border-radius: 5px; +} + +li{ + padding-bottom:15px; +} \ No newline at end of file diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..6161a80 --- /dev/null +++ b/html/index.html @@ -0,0 +1,69 @@ + + Demo static index + + + +

Static Html Site

+
+
+

+ This is a static website located on / +

+ +
    +
  1. + css/index.css +
  2. +
  3. + static url /spa1 → "./html/test/" +
  4. +
  5. + static url /spa2 → "./html/test/" +
  6. +
  7. + static url /test → "./html/test/" +
  8. + + + +
+

+
+ + + + + + + + + diff --git a/html/test/css/test.css b/html/test/css/test.css new file mode 100644 index 0000000..ec4ec0c --- /dev/null +++ b/html/test/css/test.css @@ -0,0 +1,22 @@ +p { + background-color:lightblue; + padding: 20px 5px; +} + +h1 { + text-align: center; + text-decoration: overline; +} + +div { + width: 300px; + margin: auto; + text-align: left; + background-color: yellow; +} + +hr { + width: 100px; + border: 6px solid lightcoral; + border-radius: 5px; +} \ No newline at end of file diff --git a/html/test/index.html b/html/test/index.html new file mode 100644 index 0000000..af7cdbc --- /dev/null +++ b/html/test/index.html @@ -0,0 +1,30 @@ + + Demo static "Test" + + +

Test

+

+ +
+
+

+ This is a static website located on /test but virtually accessed by /spa1 and /spa2 +

+ +
+ + +

+ +
+ + + diff --git a/http_handler.go b/http_handler.go new file mode 100644 index 0000000..68256da --- /dev/null +++ b/http_handler.go @@ -0,0 +1,24 @@ +package main + +import ( + "log" + "net/http" +) + +type httpEntry func(http.ResponseWriter, *http.Request) + +var httpEntryMap = map[string]httpEntry{ + apiV1Prefix: apiV1Main, + apiV1WebSocket: apiV1WebSocketHandler, +} + +func setupHTTPHandler() { + + for key, val := range httpEntryMap { + http.HandleFunc(key, val) + } + + log.Printf("Server started at %s:%s\n", config.Host, config.Port) + log.Fatal(http.ListenAndServe(config.Host+":"+config.Port, nil)) + // log.Fatal(http.ListenAndServeTLS(config.Host+":"+config.Port, config.TlsCert, config.TlsKey, nil)) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..75d8cad --- /dev/null +++ b/main.go @@ -0,0 +1,44 @@ +package main + +// [START import] +import ( + "log" + "net/http" +) + +// [END import] +// [START main_func] + +func main() { + + err := config.readConfig() // + if err != nil { + log.Println(err) + log.Fatalf("unable to read %s, program quit\n", configFile) + return + } + + // [START setting_port] + port := config.Port + if port == "" { + port = "8081" + log.Printf("Defaulting to port %s", port) + } + // [END setting_port] + + setupRootFileServer() + + //always last + setupHTTPHandler() +} + +// [END main_func] + +func setupRootFileServer() { + //root of doc + for idx, node := range config.Static { + log.Printf("setting up static %d with %+v\n", idx, node) + fs := http.FileServer(http.Dir(node.Dir)) + http.Handle(node.StaticUrl, http.StripPrefix(node.StripPrefix, fs)) + } +}