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 }