標籤:fun .config 建立 ack use stp 情況 參數 內容
net/http庫學習概念處理器
- ServeMux結構(擁有ServeHTTP方法,如上籤名)
- Handler結構
- 多工器 DefaultServeMux(ServeMux結構的執行個體)
處理器函數
ServeMux
- HTTP請求多工器
- __接收HTTP請求__並根據請求中的__URL__將請求重新導向到正確的處理器
- ServeMux結構也實現了ServeHTTP方法,它也是一個處理器
- ServeMux的ServeHTTP方法,調用與被請求URL相對應的__處理器__的ServeHTTP方法
最簡單的Web伺服器
import "fmt"import "net/http"// 處理器type HelloHandler struct{}func ( h *HelloHandler) ServeHTTP ( w http.ResponseWriter, r * http.Request){ fmt.Fprintf( w, "Hello" )}// 處理器函數func hello( w http.ResponseWriter, r * http.Request){ fmt.Fprintf( w, "Hello" )} func main () { server := http.Server{ Addr: "127.0.0.1:8080", //Handler: nil, //可以指定處理器 } fmt.Println("hello https://tool.lu/") //http.ListenAndServe(":8181", nil) //server.ListenAndServe() // 將 處理器 綁定到DefaultServeMux // Handle是ServeMux結構的方法,而DefaultServeMux是ServeMux的執行個體 //hello := HelloHandler{} //http.Handle("/hello", &hello) // 將函數轉換為處理器,再將處理器綁定到DefaultServeMux //http.HandleFunc( "/hello", hello ) //使用預設的多工器DefaultServeMux作為處理器 server.ListenAndServeTLS("cert.pem", "key.pem")}
http用戶端
http.NewRequest
- htp.Client -> http.request(http.NewRequest) -> client.Do(request)
- NewRequest(method, urlStr string, body io.Reader)
- request.Header.Set
http.Clinet
- cient結構api
- client參數配置
- Transport RoundTripper
- CheckRedirect func(req Request, via []Request) error
- Jar CookieJar
- Timeout time.Duration
- Transport
- 為了控制代理、安全套接層設定、保持串連、壓縮、逾時設定和其它設定,需要建立一個Transport
- MaxIdleConns
- MaxIdleConnsPerHost
tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: pool}, DisableCompression: true, } client := &http.Client{Transport: tr} resp, err := client.Get("https://example.com")tr := &http.Transport{ MaxIdleConnsPerHost: 1000, //是否表示最多建立1000個串連?}client := &http.Client{ Transport: tr,}
http
resp.Body.Close()
- 當用戶端使用完response body後必須使用close對其進行關閉
httplib學習
https://github.com/astaxie/beego
概念
- httplib庫主要用來類比用戶端發送HTTP請求
- 類似於curl工具
使用
- request對象
- debug輸出
- 設定clinet的TLS資訊
gin學習
package testsimport ( "encoding/json" "fmt" "github.com/astaxie/beego/httplib" "github.com/gin-gonic/gin" "io/ioutil" "log" "net/http" "strings" "testing" "time")func handleTestGet(c *gin.Context) { c.String(http.StatusOK, "test get OK")}func handleTestPost(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"code": 1, "message": "test post OK"})}func handleParam(c *gin.Context) { name := c.Param("name") passwd := c.Param("passwd") c.String(http.StatusOK, "name: %s, passwd: %s", name, passwd)}func handleQuery(c *gin.Context) { name := c.Query("name") passwd := c.Query("passwd") c.String(http.StatusOK, "name: %s, passwd: %s", name, passwd)}func handleHTTPLib(c *gin.Context) { c.IndentedJSON(200, gin.H{"code": 1, "data": "ok"})}func runtBasicGinServer() { fmt.Print("aa") router := gin.Default() router.GET("/test_get", handleTestGet) router.POST("/test_post", handleTestPost) router.GET("/test_param/:name/*passwd", handleParam) router.GET("/test_query", handleQuery) router.GET("/test_httplib", handleHTTPLib) group := router.Group("/v1") group.GET("/test_group", handleTestGet) router.Run(":6543")}func printGetResp(resp *http.Response) { defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("read body err %s\n", err.Error()) } log.Printf("resp body is: %+v\n", string(bodyBytes))}func printPostResp(resp *http.Response) { defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("read body err %s\n", err.Error()) } type body struct { Code int `json:"code"` Message string `json:"message"` } respBody := body{} err = json.Unmarshal(bodyBytes, &respBody) if err != nil { log.Printf("unmarshal body err %s\n", err.Error()) } log.Printf("resp body is: %+v\n", respBody)}func TestBasicClient(t *testing.T) { go runtBasicGinServer() time.Sleep(time.Second * 5) resp, err := http.Get("http://127.0.0.1:6543/test_get") if err != nil { log.Printf("get resp err %s\n", err.Error()) } printGetResp(resp) resp, err = http.Post("http://127.0.0.1:6543/test_post", "", strings.NewReader("")) if err != nil { log.Printf("get resp err %s\n", err.Error()) } printPostResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_param/name=Bob/passwd=1234") if err != nil { log.Printf("get resp err %s\n", err.Error()) } printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_param/name=Bob/") if err != nil { log.Printf("get resp err %s\n", err.Error()) } printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_param/name=Bob") if err != nil { log.Printf("get resp err %s\n", err.Error()) } printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_query?name=Alice&passwd=123") if err != nil { log.Printf("get resp err %s\n", err.Error()) } printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/v1/test_group") if err != nil { log.Printf("get resp err %s\n", err.Error()) } printGetResp(resp) res := struct { Code int `json:"code"` Message string `json:"message"` }{} if err := httplib.Get("http://127.0.0.1:6543/test_httplib").ToJSON(&res); err != nil { log.Println(err.Error()) } log.Printf("%+v", res)}func TestReuseHTTPLink(t *testing.T) { go runtBasicGinServer() time.Sleep(time.Second * 5) tr := &http.Transport{ MaxIdleConnsPerHost: 100, MaxIdleConns: 100, } c := http.Client{Transport: tr} url := "http://127.0.0.1:6543/test_get" /* 串連數, 當前 無剩餘 可用串連時 會建立; 當前 有剩餘 可用串連則 不建立 */ // use channel to control http port numbers ch := make(chan struct{}, 100) for i := 0; i < 5000; i++ { go func(i int) { ch <- struct{}{} defer func() { <-ch }() req, err := http.NewRequest("GET", url, nil) if err != nil { log.Printf("get req error %s", err.Error()) } resp, err := c.Do(req) if err != nil { log.Printf("do req error %s", err.Error()) } defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("read body error %s", err.Error()) } log.Printf("%d body: %s", i, string(bodyBytes)) }(i) //time.Sleep(time.Microsecond * 50) //time.Sleep(time.Microsecond * 50) } time.Sleep(time.Second * 10)}func TestSeqDo(t *testing.T) { go runtBasicGinServer() time.Sleep(time.Second * 5) c := http.Client{} url := "http://127.0.0.1:6543/test_get" /* defaul reuse http link there is one link to 6543 */ for i := 0; i < 5000; i++ { req, err := http.NewRequest("GET", url, nil) if err != nil { log.Printf("get req error %s", err.Error()) } resp, err := c.Do(req) if err != nil { log.Printf("do req error %s", err.Error()) } defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("read body error %s", err.Error()) } log.Printf("%d body: %s", i, string(bodyBytes)) } time.Sleep(time.Second * 10)}func TestSeqHTTPLib(t *testing.T) { go runtBasicGinServer() time.Sleep(time.Second * 5) url := "http://127.0.0.1:6543/test_get" /* ???netstat -anp | grep 6543 | grep ESTABLISHED */ for i := 0; i < 5000; i++ { bodyString, err := httplib.Get(url).String() if err != nil { log.Printf("httplib get error %s", err.Error()) } log.Printf("%d body: %s", i, bodyString) } time.Sleep(time.Second * 10)}
binding學習
github.com/gin-gonic/gin/binding
HTTPS服務參考文獻
《Go Web 編程》
Go語言_HTTP包
深入Go語言網路程式庫的基礎實現
golang中發送http請求的幾種常見情況
Go語言net/http 解讀
go net/http Client使用——長串連用戶端的使用
https://github.com/astaxie/beego
beego中文文檔
go語言 http學習