13397158231   jevian_ma@worldflying.cn

使用go语言写的简单的http服务器程序,支持代理https协议

2020-11-26 10:57:57

使用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行,编译后可直接使用。


文章作者:沃航科技

优秀产品推荐:可编程网络IO控制器

上一篇:modbus rtu的crc校验生成以及使用方法

下一篇:一个端口同时支持http代理与socks5代理---史上最强大代理服务器诞生,完全开源

联系我们

  • 地址:武汉市东湖高新开发区光谷总部国际1栋2412室
  • QQ:932773931
  • 电话:027-59761089-806
  • 手机:13397158231
  • 邮箱:jevian_ma@worldflying.cn

关注公众号

扫码添加微信

沃航(武汉)科技有限公司版权所有

备案号:鄂ICP备16014230号-1

本网站由提供CDN加速/云存储服务