Skip to content

Instantly share code, notes, and snippets.

@sekia
Created July 28, 2012 15:27
Show Gist options
  • Save sekia/3193744 to your computer and use it in GitHub Desktop.
Save sekia/3193744 to your computer and use it in GitHub Desktop.
WebSocket echo server
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var status = "LOADING";
var connectedSock;
document.onreadystatechange = function() {
if (document.readyState != 'complete') { return; }
console.debug("DOM is ready.");
updateStatus("DISCONNECTED");
};
function addToLog(side, message, timestamp) {
var logList = document.getElementById("communication-log");
var sideElm = document.createElement("dt");
var messageElm = document.createElement("dd");
sideElm.textContent = side;
messageElm.textContent = '[' + timestamp.toISOString() + '] ' + message;
logList.appendChild(sideElm);
logList.appendChild(messageElm);
}
function sendMessage() {
if (status === "DISCONNECTED") {
console.log("Not connected to a server. So the message have not been sent.")
return;
}
var text = document.getElementById("input-text").value;
console.debug("Input text: ", text);
addToLog("Client", text, new Date());
connectedSock.send(text);
}
function setupWebSocket(sock) {
sock.onopen = function() {
connectedSock = sock;
updateStatus("CONNECTED");
console.debug("Socket is ready.");
};
sock.onclose = function() {
connectedSock = null;
updateStatus("DISCONNECTED");
console.debug("Socket is closed.");
};
sock.onerror = function() {
connectedSock = null;
updateStatus("DISCONNECTED");
console.debug("Connection error occured.");
};
sock.onmessage = function(mes) {
console.debug("Recerived a message: ", mes.data);
addToLog("Server", mes.data, new Date());
};
return sock;
}
function toggleConnection() {
if (status === "DISCONNECTED") {
setupWebSocket(new WebSocket("ws://" + location.host + "/connect"));
} else if (status === "CONNECTED") {
connectedSock.close();
}
}
function updateStatus(newStatus) {
status = newStatus;
document.getElementById('status').textContent = newStatus;
document.getElementById("connect-button").textContent =
newStatus === "CONNECTED" ? "disconnect" : "connect";
}
</script>
<style>
#communication-log {
overflow: auto;
max-height: 20em;
}
</style>
<title>WebSocket sample</title>
</head>
<body>
<h1>WebSocket sample</h1>
<p>Current Status: <span id="status">LOADING</span></p>
<button id="connect-button" onclick="toggleConnection()">connect</button>
<section>
<h1>Send/Recv log</h1>
<dl id="communication-log"></dl>
<form action="javascript:void(sendMessage())">
<input id="input-text" type="text" placeholder="Enter here..." />
<button id="submit-button" type="submit">Go</button>
</form>
</section>
</body>
</html>
package main
import (
"code.google.com/p/go.net/websocket"
"errors"
"io"
"log"
"mime"
"net/http"
"os"
"strings"
)
func echo(sock *websocket.Conn) {
io.Copy(sock, sock)
}
func findMimeTypeFor(filePath string) string {
const defaultMimeType string = "application/octet-stream"
idx := strings.LastIndex(filePath, ".")
if idx < 0 {
return defaultMimeType
}
suffix := filePath[idx:]
mimeType := mime.TypeByExtension(suffix)
if mimeType == "" {
mimeType = defaultMimeType
}
return mimeType
}
func main() {
// Ya off cource these types are already registered probably so this code
// will make no sense, but harmless.
knownMimeTypes := map[string]string{
".css": "text/css",
".html": "text/html",
".js": "text/javascript",
}
for suffix, mimeType := range knownMimeTypes {
mime.AddExtensionType(suffix, mimeType)
}
http.Handle("/connect", websocket.Handler(echo))
http.HandleFunc("/static/", sendRequestedStaticFile)
http.ListenAndServe(":8080", nil)
}
func sendRequestedStaticFile(out http.ResponseWriter, req *http.Request) {
path := req.URL.Path
filePath := path[len("/static/"):]
if data, err := slurpFile(filePath); err == nil {
header := out.Header()
header.Add("Content-Type", findMimeTypeFor(filePath))
out.Write(data)
} else {
http.NotFoundHandler().ServeHTTP(out, req)
log.Println(err)
}
}
func slurpFile(path string) (data []byte, err error) {
info, err := os.Lstat(path)
if err != nil {
return
}
if info.IsDir() {
err = errors.New(info.Name() + " is a directory.")
return
}
file, err := os.Open(path)
if err != nil {
return
}
data = make([]byte, info.Size())
file.Read(data)
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment