Last active
June 27, 2024 03:02
-
-
Save owulveryck/57d8c2469fd1f8a840747b064c50ff4e to your computer and use it in GitHub Desktop.
WebSocket simple example / server in go, client in JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.addEventListener("load", function(evt) { | |
var output = document.getElementById("output"); | |
var input = document.getElementById("input"); | |
var ws; | |
var print = function(message) { | |
var d = document.createElement("div"); | |
d.innerHTML = message; | |
output.appendChild(d); | |
}; | |
document.getElementById("open").onclick = function(evt) { | |
if (ws) { | |
return false; | |
} | |
var loc = window.location, new_uri; | |
if (loc.protocol === "https:") { | |
new_uri = "wss:"; | |
} else { | |
new_uri = "ws:"; | |
} | |
new_uri += "//" + loc.host; | |
new_uri += loc.pathname + "ws"; | |
ws = new WebSocket(new_uri); | |
ws.onopen = function(evt) { | |
print("OPEN"); | |
} | |
ws.onclose = function(evt) { | |
print("CLOSE"); | |
ws = null; | |
} | |
ws.onmessage = function(evt) { | |
print("RESPONSE: " + evt.data); | |
} | |
ws.onerror = function(evt) { | |
print("ERROR: " + evt.data); | |
} | |
return false; | |
}; | |
document.getElementById("send").onclick = function(evt) { | |
if (!ws) { | |
return false; | |
} | |
print("SEND: " + input.value); | |
ws.send(input.value); | |
return false; | |
}; | |
document.getElementById("close").onclick = function(evt) { | |
if (!ws) { | |
return false; | |
} | |
ws.close(); | |
return false; | |
}; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script type="text/javascript" src="app.js"></script> | |
</head> | |
<body> | |
<table> | |
<tr> | |
<td valign="top" width="50%"> | |
<p>Click "Open" to create a connection to the server, | |
"Send" to send a message to the server and "Close" to close the connection. | |
You can change the message and send multiple times. | |
</p> | |
<form> | |
<button id="open">Open</button> | |
<button id="close">Close</button> | |
<p><input id="input" type="text" value="Hello world!"> | |
<button id="send">Send</button> | |
</form> | |
</td> | |
<td valign="top" width="50%"> | |
<div id="output"></div> | |
</td> | |
</tr> | |
</table> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"errors" | |
"github.com/gorilla/mux" | |
"github.com/gorilla/websocket" | |
"github.com/kelseyhightower/envconfig" | |
"github.com/urfave/negroni" | |
"log" | |
"net/http" | |
) | |
var ( | |
config configuration | |
upgrader = websocket.Upgrader{} // use default options | |
) | |
type configuration struct { | |
Debug bool `default:"true"` | |
Scheme string `default:"http"` | |
ListenAddress string `default:":8080"` | |
PrivateKey string `default:"ssl/server.key"` | |
Certificate string `default:"ssl/server.pem"` | |
} | |
type httpErr struct { | |
Msg string `json:"msg"` | |
Code int `json:"code"` | |
} | |
func handleErr(w http.ResponseWriter, err error, status int) { | |
msg, err := json.Marshal(&httpErr{ | |
Msg: err.Error(), | |
Code: status, | |
}) | |
if err != nil { | |
msg = []byte(err.Error()) | |
} | |
http.Error(w, string(msg), status) | |
} | |
func serveWs(w http.ResponseWriter, r *http.Request) { | |
c, err := upgrader.Upgrade(w, r, nil) | |
if err != nil { | |
handleErr(w, err, http.StatusInternalServerError) | |
return | |
} | |
defer c.Close() | |
for { | |
mt, msg, err := c.ReadMessage() | |
if err != nil { | |
handleErr(w, err, http.StatusInternalServerError) | |
break | |
} | |
if mt != websocket.TextMessage { | |
handleErr(w, errors.New("Only text message are supported"), http.StatusNotImplemented) | |
break | |
} | |
var v message | |
json.Unmarshal(msg, &v) | |
err = c.WriteMessage(mt, []byte(msg)) | |
if err != nil { | |
handleErr(w, err, http.StatusInternalServerError) | |
break | |
} | |
} | |
} | |
func main() { | |
// Default values | |
err := envconfig.Process("SOCKETCAM", &config) | |
if err != nil { | |
log.Fatal(err.Error()) | |
} | |
if config.Debug { | |
log.Printf("==> SCHEME: %v", config.Scheme) | |
log.Printf("==> ADDRESS: %v", config.ListenAddress) | |
log.Printf("==> PRIVATEKEY: %v", config.PrivateKey) | |
log.Printf("==> CERTIFICATE: %v", config.Certificate) | |
} | |
router := newRouter() | |
n := negroni.Classic() | |
n.UseHandler(router) | |
if config.Scheme == "https" { | |
log.Fatal(http.ListenAndServeTLS(config.ListenAddress, config.Certificate, config.PrivateKey, n)) | |
} else { | |
log.Fatal(http.ListenAndServe(config.ListenAddress, n)) | |
} | |
} | |
// NewRouter is the constructor for all my routes | |
func newRouter() *mux.Router { | |
router := mux.NewRouter().StrictSlash(true) | |
router. | |
Methods("GET"). | |
Path("/ws"). | |
Name("Communication Channel"). | |
HandlerFunc(serveWs) | |
router. | |
Methods("GET"). | |
PathPrefix("/"). | |
Name("Static"). | |
Handler(http.FileServer(http.Dir("./htdocs"))) | |
return router | |
} | |
solutions
var wsUpgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example don`t work, function c, err := upgrader.Upgrade(w, r, nil) always returns websocket: request origin not allowed by Upgrader.CheckOrigin