Created
December 9, 2012 09:26
-
-
Save koyachi/4244025 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
// Usage: | |
// % go run wstail.go a.txt | |
// or | |
// % go build wstail.go | |
// % wstail a.txt | |
import ( | |
"code.google.com/p/go.net/websocket" | |
"fmt" | |
"io" | |
"net/http" | |
"os" | |
"os/exec" | |
) | |
func indexHandler(w http.ResponseWriter, req *http.Request) { | |
io.WriteString(w, `<html> | |
<head> | |
<style> | |
body | |
{ color: #1a2c37; | |
font-family: 'Helvetica', sans-serif; font-size: 86%; | |
padding: 2em; } | |
#info | |
{ font-size: 120%; | |
font-weight: bold; } | |
#tail | |
{ border: 1px solid #ccc; | |
height: 300px; | |
padding: 0.5em; | |
overflow: hidden; | |
position: relative; | |
overflow-y: scroll; } | |
</style> | |
<script type="text/javascript"> | |
var header = "[wstail]" | |
var ws; | |
function init() { | |
console.log("init"); | |
if (ws != null) { | |
ws.close(); | |
ws = null; | |
} | |
path = "/tail"; | |
console.log("path:" + path); | |
var div = document.getElementById("tail"); | |
div.innerText = div.innerText + header + "path:" + path + "\n"; | |
ws = new WebSocket("ws://localhost:23456" + path); | |
ws.onopen = function () { | |
div.innerText = div.innerText + header + "opened\n"; | |
}; | |
ws.onmessage = function (e) { | |
console.log(e.data); | |
div.innerText = div.innerText + e.data; | |
if (e.data instanceof ArrayBuffer) { | |
s = "ArrayBuffer: " + e.data.byteLength + "["; | |
var view = new Uint8Array(e.data); | |
for (var i = 0; i < view.length; ++i) { | |
s += " " + view[i]; | |
} | |
s += "]"; | |
div.innerText = div.innerText + s + "\n"; | |
} | |
}; | |
ws.onclose = function (e) { | |
div.innerText = div.innerText + header + "closed\n"; | |
}; | |
console.log("init"); | |
div.innerText = div.innerText + header + "init\n"; | |
}; | |
</script> | |
<body onLoad="init();"> | |
<pre id="info"></pre> | |
<pre id="tail"></pre> | |
</html> | |
`) | |
} | |
func startTail(file string, ch chan string) error { | |
tail := exec.Command("tail", "-f", file) | |
stdout, err := tail.StdoutPipe() | |
if err != nil { | |
return err | |
} | |
if err := tail.Start(); err != nil { | |
return err | |
} | |
go func() { | |
buf := make([]byte, 4*1024) | |
for { | |
//buf := make([]byte, 100) | |
n, err := stdout.Read(buf) | |
if err != nil { | |
panic("reader.ReadString(): " + err.Error()) | |
return | |
} | |
line := string(buf[0:n]) | |
fmt.Printf("read[%v:%v]\n", n, line) | |
ch <- line | |
} | |
}() | |
return nil | |
} | |
func makeWebsocketHandlerWithChannel(ch chan string, f func(chan string, *websocket.Conn)) func(*websocket.Conn) { | |
return func(ws *websocket.Conn) { | |
f(ch, ws) | |
} | |
} | |
func websocketTailHandler(ch chan string, ws *websocket.Conn) { | |
fmt.Printf("tailHandler %v\n", ws) | |
for { | |
line := <-ch | |
if err := websocket.Message.Send(ws, line); err != nil { | |
fmt.Println("ERR:websoket.Message.Send(): " + err.Error()) | |
} | |
fmt.Printf("tailHandler write[%v]\n", line) | |
} | |
fmt.Println("tailHandler finished") | |
} | |
// for debug | |
func pseudoSubscriber(ch chan string) { | |
for { | |
line := <-ch | |
fmt.Println("[sub]: " + line) | |
} | |
} | |
func main() { | |
ch := make(chan string) | |
http.Handle("/tail", websocket.Handler(makeWebsocketHandlerWithChannel(ch, websocketTailHandler))) | |
http.HandleFunc("/", indexHandler) | |
if err := startTail(os.Args[1], ch); err != nil { | |
panic(err) | |
} | |
fmt.Println("start wstail...") | |
err := http.ListenAndServe(":23456", nil) | |
if err != nil { | |
panic("ListenAndServe: " + err.Error()) | |
} | |
//pseudoSubscriber(ch) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment