Code snippet 1
package main
import (
"bufio"
"fmt"
"io"
"log"
"net/http"
"os/exec"
"github.com/nbari/violetear"
)
func main() {
// http.HandleFunc("/", handleRequest)
// http.ListenAndServe(":8888", nil)
router := violetear.New()
router.HandleFunc("/cmd", handleRequest, "GET")
router.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}, "GET")
log.Fatal(http.ListenAndServe(":8888", router))
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-cache")
// 使浏览器页面的滚动条始终置于底部
scroll := `<body style="word-wrap: break-word; white-space: pre-wrap; background-color: #444; color: #fff; font-family: mono"><script>
const resizeObserver = new ResizeObserver(() =>
window.scrollTo(0, document.body.scrollHeight)
)
// start observing a DOM node
resizeObserver.observe(document.body)
</script></body>
`
fmt.Fprint(w, scroll)
// cmd := exec.Command("ping", "-4", "www.tumupan.com", "-c", "4") // 执行ping命令
cmd := exec.Command("ifconfig")
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Println("Error:", err)
return
}
err = cmd.Start()
if err != nil {
log.Println("Error:", err)
return
}
reader := bufio.NewReader(stdout)
for {
line, err := reader.ReadString('\n')
if err != nil || io.EOF == err {
log.Println("Command is finished.")
break
}
fmt.Fprintf(w, line) // 将输出写入http响应
w.(http.Flusher).Flush() // 刷新http响应
}
err = cmd.Wait()
if err != nil {
log.Println("Error:", err)
return
}
}
Code snippet 2
package main
import (
"bufio"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"github.com/nbari/violetear"
)
func stream(w http.ResponseWriter, r *http.Request) {
// 使浏览器页面的滚动条始终置于底部
scroll := `
<body style="word-wrap: break-word; white-space: pre-wrap;"><script>
const resizeObserver = new ResizeObserver(() =>
window.scrollTo(0, document.body.scrollHeight)
)
// start observing a DOM node
resizeObserver.observe(document.body)
</script></body>
`
fmt.Fprint(w, scroll)
ctx := r.Context()
ch := make(chan struct{})
// 每1秒输出一个数,逐渐递增
cmd := exec.CommandContext(ctx, "ping", "www.baidu.com")
rPipe, wPipe, err := os.Pipe()
if err != nil {
log.Fatal(err)
}
cmd.Stdout = wPipe
cmd.Stderr = wPipe
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
go writeOutput(w, rPipe)
go func(ch chan struct{}) {
cmd.Wait()
wPipe.Close()
ch <- struct{}{}
}(ch)
select {
case <-ch:
case <-ctx.Done():
err := ctx.Err()
log.Printf("Client disconnected: %s\n", err)
}
}
func writeOutput(w http.ResponseWriter, input io.ReadCloser) {
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming not supported", http.StatusInternalServerError)
return
}
// Important to make it work in browsers
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
in := bufio.NewScanner(input)
for in.Scan() {
data := in.Text()
log.Printf("data: %s\n", data)
fmt.Fprintf(w, "data: %s\n", data)
flusher.Flush()
}
input.Close()
}
func main() {
router := violetear.New()
router.HandleFunc("/", stream, "GET")
log.Fatal(http.ListenAndServe(":8080", router))
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 admin@yantu.org