package main
import (
"bufio"
"bytes"
"errors"
"io"
"log"
"net"
"net/http"
"os"
"sync"
"time"
)
// StdioConn 实现 net.Conn 接口,将 stdin/stdout 作为连接
type StdioConn struct {
reader *bufio.Reader
writer *bufio.Writer
closed bool
closeCh chan struct{}
mutex sync.Mutex
deadline time.Time
}
func NewStdioConn(closeCh chan struct{}) *StdioConn {
return &StdioConn{
reader: bufio.NewReader(bytes.NewBufferString("GET /alert/danger HTTP/1.1\nAccept: */*\nAccept-Encoding: gzip, deflate, br, zstd\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\nConnection: keep-alive\nContent-Length: 286\nContent-Type: application/json\nCookie: authelia_session=0gWp$SqPocUb30Ni*7Fkwd3Mh8PBNvwo; _SESSION=j 77m5hhT3CbRr6lzYOMeD3Sx0dgO0JIB/k1a X29Xwb786HrmZmeCPUa7OcpCkc0bAEH8Fq424TIhmMpS0ZkWShVRcblieE438E8xseHwOcIuzciLDF NjaVNb7y WHmuiDgL4wb8cBbP7XVr5o0CpnAj6EUstJSRguyCGbZb3ZBnP6mL0=\nDNT: 1\nHost: run.coocn.cn\nOrigin: https://run.coocn.cn\nReferer: https://run.coocn.cn/new/go\nSec-Fetch-Dest: empty\nSec-Fetch-Mode: cors\nSec-Fetch-Site: same-origin\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36\nsec-ch-ua: \"Google Chrome\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"\nsec-ch-ua-mobile: ?0\nsec-ch-ua-platform: \"Windows\"\n\n")),
// reader: bufio.NewReader(os.Stdin),
writer: bufio.NewWriter(os.Stdout),
closeCh: closeCh,
}
}
func (c *StdioConn) Read(b []byte) (n int, err error) {
c.mutex.Lock()
defer c.mutex.Unlock()
if c.closed {
return 0, io.EOF
}
if !c.deadline.IsZero() && time.Now().After(c.deadline) {
return 0, errors.New("read timeout")
}
return c.reader.Read(b)
}
func (c *StdioConn) Write(b []byte) (n int, err error) {
c.mutex.Lock()
defer c.mutex.Unlock()
if c.closed {
return 0, io.EOF
}
n, err = c.writer.Write(b)
if err != nil {
return n, err
}
return n, c.writer.Flush()
}
func (c *StdioConn) Close() error {
c.mutex.Lock()
defer c.mutex.Unlock()
log.Println("关闭 StdioConn...")
close(c.closeCh)
c.closed = true
return nil
}
func (c *StdioConn) LocalAddr() net.Addr {
return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}
}
func (c *StdioConn) RemoteAddr() net.Addr {
return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}
}
func (c *StdioConn) SetDeadline(t time.Time) error {
c.mutex.Lock()
defer c.mutex.Unlock()
c.deadline = t
return nil
}
func (c *StdioConn) SetReadDeadline(t time.Time) error {
return c.SetDeadline(t)
}
func (c *StdioConn) SetWriteDeadline(t time.Time) error {
return c.SetDeadline(t)
}
// ------------------------------
// 实现一个 net.Listener
// ------------------------------
type stdioListener struct {
conn net.Conn
done chan struct{}
close chan struct{}
}
func NewStdioListener() *stdioListener {
done := make(chan struct{})
return &stdioListener{
conn: NewStdioConn(done),
done: done,
close: make(chan struct{}),
}
}
func (l *stdioListener) Wait() {
<-l.done
}
func (l *stdioListener) Accept() (net.Conn, error) {
if l.conn != nil {
conn := l.conn
l.conn = nil
return conn, nil
}
log.Println("!!!!111...")
log.Println("!!!!222...")
<-l.close
log.Println("!!!!333...")
return nil, net.ErrClosed
}
func (l *stdioListener) Close() error {
log.Println("关闭 stdioListener...")
close(l.close)
return nil
}
func (l *stdioListener) Addr() net.Addr { return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)} }
func main() {
// 定义 HTTP handler
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte("Hello from stdin/stdout HTTP server!\n"))
})
server := &http.Server{
Handler: handler,
}
// 创建标准输入输出监听器
listener := NewStdioListener()
// 在标准输入输出连接上处理单个HTTP请求
log.Println("启动标准输入输出HTTP服务器...")
go func() {
listener.Wait()
log.Println("关闭 Server...")
log.Println("关闭标准输入输出HTTP服务器: ", server.Close())
}()
// 启动 HTTP 服务
if err := server.Serve(listener); err != nil {
if err != http.ErrServerClosed {
panic(err)
}
}
}
{
"in":"http",
"out":"http"
}