当前位置: 首页 > 工具软件 > Bastion > 使用案例 >

micro-bastion---迷你HTTP代理--go开源

谭刚毅
2023-12-01

 项目地址:

https://github.com/fractorysolutions/micro-bastion

欢迎大家给我提issue

https://github.com/allenXu317/micro-bastion/tree/comment-version

很友好得项目,既有docker在linux环境下运行,也能直接在win写built,方便实验。

package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"strings"
)

func handleRequest(w http.ResponseWriter, r *http.Request) {
	//有个现像,当url为:localhost:8888时,会出现多个报错信息,说明go的listen是一个连接对应多个请求
    //所以我给提了个issue并且提出了修改得意见
	if r.URL.Path == "/" {
		fmt.Fprintln(w, "Bastion is up ")
		return
	}
	r.URL = calculateURL(r)
	//若新URL的HOST为空则直接返回结束进程
	if r.URL.Host == "" {
		log.Println("Requesting nothing")
		return
	}
	r.Host = r.URL.Host
	log.Println("Requesting ", r.URL)
    //发起请求
    //开始转发
	resp, err := http.DefaultTransport.RoundTrip(r)

	if err != nil {
		log.Println("Could not fetch ", r.URL, ": ", err)
		http.Error(w, err.Error(), http.StatusServiceUnavailable)
		return
	}

	defer resp.Body.Close()
    
    //写入相关得响应头、状态码、实体数据
    //实现转发代理功能
	copyHeader(resp.Header, w)
	w.WriteHeader(resp.StatusCode)
	io.Copy(w, resp.Body)
}

//得到转发的HTTP头部
func copyHeader(from http.Header, to http.ResponseWriter) {
	toHeader := to.Header()
	for k, vs := range from {
		for _, v := range vs {
			toHeader.Add(k, v)
		}
	}
}

//得到需要代理访问的url
func calculateURL(r *http.Request) *url.URL {
	newURL := *r.URL
	oldPath := r.URL.Path
	oldPathParts := strings.Split(oldPath, "/")[1:]
	log.Println("This is oldPath:", oldPath, strings.Split(oldPath, "/"), oldPathParts, len(oldPathParts))
	//之前的代码没有这个判断,但是在浏览器访问时会有数组溢出报错信息
	//排错得知是在字符串切割后并没有进行数组长度的判断,会使程序异常
	if len(oldPathParts) <= 1 {
		log.Println("The URL is too short ")
		newURL.Host = ""
		newURL.Path = ""
		newURL.Scheme = ""
		return &newURL
	}
	newURL.Host = oldPathParts[0] + ":" + oldPathParts[1]
	newURL.Path = "/" + strings.Join(oldPathParts[2:], "/")

	newURL.Scheme = "http"

	return &newURL
}

func main() {
	//定义一个命令行flag
	//flag 名称:port 默认值:8888,提示信息:
	var port = flag.Int("port", 8888, "port that micro-bastion should listen on")
	flag.Parse()

	//打印提示信息
	log.Println("Starting micro-bastion on port", *port)

	//注册http server服务
	server := &http.Server{
		//监听的host:port
		Addr: fmt.Sprint(":", *port),
		//进行强制类型转换,将handleRequest转换为HandlerFunc类型,进行路由注册
		Handler:           http.HandlerFunc(handleRequest),
		ReadTimeout:       0,
		ReadHeaderTimeout: 0,
		WriteTimeout:      0,
		IdleTimeout:       0,
	}

	// start the server
	log.Fatal(server.ListenAndServe())
}

 

 

 类似资料: