使用go语言写的简单的http服务器程序,支持https代理以及直连。话不多说,直接上代码。
package main
import (
"bytes"
"log"
"net"
"io"
"net/url"
"runtime"
"strings"
)
func main() {
runtime.GOMAXPROCS(1)
log.SetFlags(log.LstdFlags | log.Lshortfile)
log.Println("version: " + runtime.Version())
HttpAccept(8888)
}
func HttpAccept (port int) {
tcpaddr := &net.TCPAddr{
IP: []byte{0, 0, 0, 0},
Port: port,
Zone: "",
}
l, err := net.ListenTCP("tcp", tcpaddr)
if err != nil {
log.Println(err)
return
}
for {
client, err := l.AcceptTCP()
if err != nil {
log.Println(err)
l.Close()
return
}
go HttpProxyRequest(client)
}
}
func HttpProxyRequest (client *net.TCPConn) {
client.SetReadBuffer(32*1024)
client.SetWriteBuffer(32*1024)
b := make([]byte, 32*1024)
n, err := client.Read(b)
if err != nil {
log.Println(err)
client.Close()
return
}
maddr := bytes.IndexByte(b, ' ')
method := string(b[:maddr])
host := string(b[maddr+1:maddr+1+bytes.IndexByte(b[maddr+1:], ' ')])
if method == "CONNECT" {
log.Println(host)
tcpaddr, err := net.ResolveTCPAddr("tcp", host)
if err != nil {
log.Println(err)
client.Close()
return
}
server, err := net.DialTCP("tcp", nil, tcpaddr)
if err != nil {
log.Println(err)
client.Close()
return
}
server.SetReadBuffer(32*1024)
server.SetWriteBuffer(32*1024)
_, err = client.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
if err != nil {
log.Println(err)
client.Close()
server.Close()
return
}
go IoCopy(client, server)
go IoCopy(server, client)
} else {
hostPortURL, err := url.Parse(host)
if err != nil {
log.Println(err)
client.Close()
return
}
address := hostPortURL.Host
if strings.Index(address, ":") == -1 {
address = address + ":80"
}
log.Println(address)
tcpaddr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
log.Println(err)
client.Close()
return
}
server, err := net.DialTCP("tcp", nil, tcpaddr)
if err != nil {
log.Println(err)
client.Close()
return
}
server.SetReadBuffer(32*1024)
server.SetWriteBuffer(32*1024)
httpheadlen := bytes.Index(b, []byte("\r\n\r\n"))+4
httphead := b[:httpheadlen]
start := bytes.Index(httphead, []byte(hostPortURL.Host)) + len(hostPortURL.Host)
if start != -1 {
httphead = append(httphead[:maddr+1], httphead[start:]...)
}
start = bytes.Index(httphead, []byte("Proxy-Connection:"))
if start != -1 {
httphead = append(httphead[:start], httphead[start+6:]...)
}
if httpheadlen < n {
b = append(httphead, b[httpheadlen:n]...)
} else {
b = httphead
}
_, err = server.Write(b)
if err != nil {
log.Println(err)
client.Close()
server.Close()
return
}
go IoCopy(client, server)
go IoCopy(server, client)
}
}
func IoCopy(dst *net.TCPConn, src *net.TCPConn) {
io.Copy(dst, src)
dst.Close()
}一共134行,编译后可直接使用。
文章作者:沃航科技