github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgNet/kmgHttp/goHttp.go (about)

     1  package kmgHttp
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"net"
    10  	"net/http"
    11  	"net/http/httputil"
    12  	"strings"
    13  	"time"
    14  
    15  	"crypto/tls"
    16  	"github.com/bronze1man/kmg/kmgNet"
    17  )
    18  
    19  func NewRequestFromByte(r []byte) (req *http.Request, err error) {
    20  	return http.ReadRequest(bufio.NewReader(bytes.NewReader(r)))
    21  }
    22  
    23  //sometimes it is hard to remember how to get response from bytes ...
    24  func NewResponseFromBytes(r []byte) (resp *http.Response, err error) {
    25  	return http.ReadResponse(bufio.NewReader(bytes.NewBuffer(r)), &http.Request{})
    26  }
    27  
    28  //sometimes it is hard to remember how to dump response to bytes
    29  func DumpResponseToBytes(resp *http.Response) (b []byte, err error) {
    30  	return httputil.DumpResponse(resp, true)
    31  }
    32  
    33  func ResponseReadAllBody(resp *http.Response) (b []byte, err error) {
    34  	defer resp.Body.Close()
    35  	return ioutil.ReadAll(resp.Body)
    36  }
    37  
    38  func RequestReadAllBody(req *http.Request) (b []byte, err error) {
    39  	defer req.Body.Close()
    40  	return ioutil.ReadAll(req.Body)
    41  }
    42  
    43  func MustResponseReadAllBody(resp *http.Response) (b []byte) {
    44  	defer resp.Body.Close()
    45  	b, err := ioutil.ReadAll(resp.Body)
    46  	if err != nil {
    47  		panic(err)
    48  	}
    49  	return b
    50  }
    51  
    52  func UrlGetContent(url string) (b []byte, err error) {
    53  	resp, err := http.Get(url)
    54  	if err != nil {
    55  		return
    56  	}
    57  	return ResponseReadAllBody(resp)
    58  }
    59  
    60  func MustUrlGetContent(url string) (b []byte) {
    61  	resp, err := http.Get(url)
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  	b, err = ResponseReadAllBody(resp)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  	return b
    70  }
    71  
    72  func HeaderToString(header http.Header) (s string) {
    73  	buf := &bytes.Buffer{}
    74  	header.Write(buf)
    75  	return string(buf.Bytes())
    76  }
    77  
    78  //把request转换成[]byte,并且使body可以被再次读取
    79  func MustRequestToStringCanRead(req *http.Request) (s string) {
    80  	oldBody := req.Body
    81  	defer oldBody.Close()
    82  	body, err := ioutil.ReadAll(req.Body)
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  	req.Body = ioutil.NopCloser(bytes.NewReader(body))
    87  	buf := &bytes.Buffer{}
    88  	req.Write(buf)
    89  	req.Body = ioutil.NopCloser(bytes.NewReader(body))
    90  	return string(buf.Bytes())
    91  }
    92  
    93  func MustRequestFromString(reqString string) (req *http.Request) {
    94  	req, err := http.ReadRequest(bufio.NewReader(bytes.NewReader([]byte(reqString))))
    95  	if err != nil {
    96  		panic(err)
    97  	}
    98  	return req
    99  }
   100  
   101  // 进行http代理,并且代理到writer上面去
   102  // 调用时,请修改req的参数,避免自己调用自己
   103  // 如果出现错误,(对方服务器连不上之类的,不会修改w,会返回一个error
   104  // 不跟踪redirect(跟踪redirect会导致redirect的请求的内容被返回)
   105  func HttpProxyToWriter(w http.ResponseWriter, req *http.Request) (err error) {
   106  	resp, err := HttpRoundTrip(req)
   107  	if err != nil {
   108  		return err
   109  	}
   110  	HttpResponseToWrite(resp, w)
   111  	return
   112  }
   113  
   114  func HttpRoundTrip(req *http.Request) (resp *http.Response, err error) {
   115  	req.RequestURI = ""
   116  	if req.Proto == "" {
   117  		req.Proto = "HTTP/1.1"
   118  	}
   119  	if req.URL.Scheme == "" {
   120  		req.URL.Scheme = "http"
   121  	}
   122  	resp, err = http.DefaultTransport.RoundTrip(req) //使用这个避免跟进 redirect
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	return
   127  }
   128  
   129  func HttpResponseToWrite(resp *http.Response, w http.ResponseWriter) {
   130  	defer resp.Body.Close()
   131  	for k, values := range resp.Header {
   132  		for _, value := range values {
   133  			w.Header().Add(k, value)
   134  		}
   135  	}
   136  	w.WriteHeader(resp.StatusCode)
   137  	io.Copy(w, resp.Body)
   138  }
   139  
   140  //会把request里面的东西全部都读出来(body)
   141  func HttpRequestClone(in *http.Request) (out *http.Request, err error) {
   142  	buf := &bytes.Buffer{}
   143  	err = in.Write(buf)
   144  	if err != nil {
   145  		return
   146  	}
   147  	out, err = http.ReadRequest(bufio.NewReader(buf))
   148  	if err != nil {
   149  		return
   150  	}
   151  	return
   152  }
   153  
   154  func MustHttpRequestClone(in *http.Request) *http.Request {
   155  	out, err := HttpRequestClone(in)
   156  	if err != nil {
   157  		panic(err)
   158  	}
   159  	return out
   160  }
   161  
   162  //清空默认的Http服务器的路径表
   163  func ClearHttpDefaultServer() {
   164  	http.DefaultServeMux = http.NewServeMux()
   165  }
   166  
   167  func Redirect301ToNewHost(w http.ResponseWriter, req *http.Request, scheme string, host string) {
   168  	u := req.URL
   169  	u.Host = host
   170  	if u.Scheme == "" {
   171  		u.Scheme = scheme
   172  	}
   173  	http.Redirect(w, req, u.String(), 301)
   174  }
   175  
   176  func MustUrlGetContentProcess(url string) (b []byte) {
   177  	fmt.Print("\nConnnecting\r")
   178  	resp, err := http.Get(url)
   179  	if err != nil {
   180  		return
   181  	}
   182  	printProgress(0, resp.ContentLength, 0, 0)
   183  	defer resp.Body.Close()
   184  	buf := bytes.Buffer{}
   185  	bufBytes := make([]byte, 32*1024)
   186  	lastTime := time.Now()
   187  	lastBytes := 0
   188  	for {
   189  		n, err := resp.Body.Read(bufBytes)
   190  		if n > 0 {
   191  			buf.Write(bufBytes[:n])
   192  			now := time.Now()
   193  			if now.After(lastTime.Add(1 * time.Second)) {
   194  				thisBytes := buf.Len()
   195  				printProgress(int64(thisBytes), resp.ContentLength, now.Sub(lastTime), thisBytes-lastBytes)
   196  				lastTime = now
   197  				lastBytes = thisBytes
   198  			}
   199  		}
   200  		if err == io.EOF {
   201  			fmt.Println()
   202  			return buf.Bytes()
   203  		}
   204  		if err != nil {
   205  			panic(err)
   206  		}
   207  	}
   208  }
   209  
   210  func printProgress(get int64, total int64, dur time.Duration, lastBytes int) {
   211  	percent := 0.0
   212  	if total <= 0 {
   213  		percent = 0.0
   214  	} else if total < get {
   215  		percent = 1.0
   216  	} else {
   217  		percent = float64(get) / float64(total)
   218  	}
   219  	showNum := int(percent * 40)
   220  	notShowNum := 40 - showNum
   221  	fmt.Printf("%s%s %.2f%% %s/%s %s     \r",
   222  		strings.Repeat("#", showNum), strings.Repeat(" ", notShowNum), percent*100,
   223  		kmgNet.SizeString(get), kmgNet.SizeString(total), kmgNet.SpeedString(lastBytes, dur))
   224  }
   225  
   226  // 异步开启一个http服务器,这个服务器可以使用返回的closer关闭
   227  func MustGoHttpAsyncListenAndServeWithCloser(addr string, handler http.Handler) (closer func() error) {
   228  	srv := &http.Server{Addr: addr, Handler: handler}
   229  	if addr == "" {
   230  		addr = ":80"
   231  	}
   232  	ln, err := net.Listen("tcp", addr)
   233  	if err != nil {
   234  		panic(err)
   235  	}
   236  	go func() {
   237  		err := srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
   238  		if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
   239  			panic(err)
   240  		}
   241  	}()
   242  	return ln.Close
   243  }
   244  
   245  func MustGoHttpsAsyncListenAndServeWithCloser(addr string, tlsConfig *tls.Config, handler http.Handler) (closer func() error) {
   246  	srv := &http.Server{Addr: addr, Handler: handler}
   247  	/*
   248  		cert, err := tls.X509KeyPair([]byte(certS), []byte(keyS))
   249  		if err != nil {
   250  			return err
   251  		}
   252  		srv.TLSConfig = &tls.Config{
   253  			Certificates: []tls.Certificate{cert},
   254  			NextProtos:   []string{"http/1.1"},
   255  		}
   256  	*/
   257  	srv.TLSConfig = tlsConfig
   258  	ln, err := net.Listen("tcp", addr)
   259  	if err != nil {
   260  		panic(err)
   261  	}
   262  
   263  	tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig)
   264  	go func() {
   265  		err := srv.Serve(tlsListener)
   266  		if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
   267  			panic(err)
   268  		}
   269  	}()
   270  	return tlsListener.Close
   271  }
   272  
   273  // tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
   274  // connections. It's used by ListenAndServe and ListenAndServeTLS so
   275  // dead TCP connections (e.g. closing laptop mid-download) eventually
   276  // go away.
   277  type tcpKeepAliveListener struct {
   278  	*net.TCPListener
   279  }
   280  
   281  func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
   282  	tc, err := ln.AcceptTCP()
   283  	if err != nil {
   284  		return
   285  	}
   286  	tc.SetKeepAlive(true)
   287  	tc.SetKeepAlivePeriod(3 * time.Minute)
   288  	return tc, nil
   289  }
   290  
   291  func GoListenAndServeTLSWithCertContent(addr string, certS string, keyS string, handler http.Handler) error {
   292  	srv := &http.Server{Addr: addr, Handler: handler}
   293  	cert, err := tls.X509KeyPair([]byte(certS), []byte(keyS))
   294  	if err != nil {
   295  		return err
   296  	}
   297  	srv.TLSConfig = &tls.Config{
   298  		Certificates: []tls.Certificate{cert},
   299  		NextProtos:   []string{"http/1.1"},
   300  	}
   301  
   302  	ln, err := net.Listen("tcp", addr)
   303  	if err != nil {
   304  		return err
   305  	}
   306  
   307  	tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig)
   308  	return srv.Serve(tlsListener)
   309  }
   310  
   311  // 去掉cert和key,复制粘帖带来的各种格式错误
   312  func FormatHttpsCertOrKey(inS string) string {
   313  	inS = strings.TrimSpace(inS)
   314  	return inS
   315  }