Go pkg学与练 - http

Stanley · · 1369 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go http package 包含了http client 和 http server 的实现。主要文件有: ~~~ client.go cookie.go header.go http.go method.go request.go response.go server.go transport.go ~~~ Server.go: --------- 我们先从一个简单的http server开始。创建一个http服务需要有三个步骤: * 创建ServerMux:将预定义的url列表与Hanlder相关联。 * 创建Handler:负责对http请求进行处理,返回http响应。 * 监听给定的地址及端口提供http服务。 ~~~ package main import ( "fmt" "html" "log" "net/http" ) func fooHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) } func main() { mux := http.NewServeMux() handler := http.HandlerFunc(fooHandler) mux.Handle("/foo", handler) log.Fatal(http.ListenAndServe(":8080", mux)) } ~~~ ServeMux: ~~~ // ServeMux 结构 type ServeMux struct { mu sync.RWMutex // 这个map用于存放http url entries, 而每个erntry 包含了一个Handler // 对应上面的例子:m = {"/foo":fooHandler(ResponseWriter, *Request)} m map[string]muxEntry hosts bool // whether any patterns contain hostnames } type muxEntry struct { explicit bool h Handler pattern string } func NewServeMux() *ServeMux { return new(ServeMux) } func (mux *ServeMux) match(path string) (h Handler, pattern string) { // 根据request找出对应的Handler func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) { func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) { // 将request 分发给Handler处理 func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { // 注册Handler func (mux *ServeMux) Handle(pattern string, handler Handler) { func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { ~~~ DefaultServeMux: ~~~ var DefaultServeMux = &defaultServeMux var defaultServeMux ServeMux func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) { // 上面的例子用defaultServeMux,可以简化为: func main() { handler := http.HandlerFunc(fooHandler) http.Handle("/foo", handler) log.Fatal(http.ListenAndServe(":8080", nil)) } 或者 func main() { http.HandleFunc("/foo", fooHandler) log.Fatal(http.ListenAndServe(":8080", nil)) } ~~~ Handler: ~~~ type Handler interface { ServeHTTP(ResponseWriter, *Request) } // f 实现接口 Handler ServeHTTP type HandlerFunc func(ResponseWriter, *Request) func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) } // 已定义好的一些处理器 func NotFoundHandler() Handler { return HandlerFunc(NotFound) } func RedirectHandler(url string, code int) Handler { func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler { ~~~ ListenAndServe: ~~~ // server 结构 type Server struct { Addr string // TCP address to listen on, ":http" if empty Handler Handler // handler to invoke, http.DefaultServeMux if nil TLSConfig *tls.Config // optional TLS config, used by ServeTLS and ListenAndServeTLS ReadTimeout time.Duration ReadHeaderTimeout time.Duration WriteTimeout time.Duration IdleTimeout time.Duration MaxHeaderBytes int TLSNextProto map[string]func(*Server, *tls.Conn, Handler) ConnState func(net.Conn, ConnState) ErrorLog *log.Logger disableKeepAlives int32 // accessed atomically. inShutdown int32 // accessed atomically (non-zero means we're in Shutdown) nextProtoOnce sync.Once // guards setupHTTP2_* init nextProtoErr error // result of http2.ConfigureServer if used mu sync.Mutex listeners map[net.Listener]struct{} activeConn map[*conn]struct{} doneChan chan struct{} onShutdown []func() } // 创建Server,调用ListenAndServe func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() } func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServeTLS(certFile, keyFile) } // 调用net.Listen()进行监听 func (srv *Server) ListenAndServe() error { func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { // 接着调用server.Serve负责处理请求 func (srv *Server) Serve(l net.Listener) error { func (srv *Server) ServeTLS(l net.Listener, certFile, keyFile string) error { // Serve()调用Accept获取连接数据, 并创建conn, go c.serve()处理请求 func (srv *Server) newConn(rwc net.Conn) *conn { /* conn 结构 type conn struct { server *Server cancelCtx context.CancelFunc rwc net.Conn remoteAddr string tlsState *tls.ConnectionState werr error r *connReader bufr *bufio.Reader bufw *bufio.Writer lastMethod string curReq atomic.Value // of *response (which has a Request in it) curState atomic.Value // of ConnState mu sync.Mutex hijackedv bool }*/ // c.readRequest()读取请求, 调用Handler ServeHTTP() func (c *conn) serve(ctx context.Context) { Server中其他methods: func (srv *Server) maxHeaderBytes() int { func (srv *Server) initialReadLimitSize() int64 { func (srv *Server) Close() error { func (srv *Server) Shutdown(ctx context.Context) error { func (srv *Server) RegisterOnShutdown(f func()) { func (srv *Server) shouldConfigureHTTP2ForServe() bool { func (srv *Server) SetKeepAlivesEnabled(v bool) { func (srv *Server) setupHTTP2_ServeTLS() error { func (srv *Server) setupHTTP2_Serve() error { func (srv *Server) onceSetNextProtoDefaults_Serve() { func (srv *Server) onceSetNextProtoDefaults() { Conn中其他methods: func (c *conn) hijacked() bool { func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) { func (c *conn) readRequest(ctx context.Context) (w *response, err error) { func (c *conn) finalFlush() { func (c *conn) close() { func (c *conn) closeWriteAndWait() { func (c *conn) setState(nc net.Conn, state ConnState) { func (c *conn) serve(ctx context.Context) { ~~~ ResponseWrite: ~~~ type ResponseWriter interface { Header() Header Write([]byte) (int, error) WriteHeader(int) } // response struct 实现 http.ResponseWriter type response struct { conn *conn req *Request // request for this response reqBody io.ReadCloser cancelCtx context.CancelFunc // when ServeHTTP exits wroteHeader bool // reply header has been (logically) written wroteContinue bool // 100 Continue response was written wants10KeepAlive bool // HTTP/1.0 w/ Connection "keep-alive" wantsClose bool // HTTP request has Connection "close" // 例子中的字符串“hello ...”会写在w中 w *bufio.Writer // buffers output in chunks to chunkWriter cw chunkWriter handlerHeader Header calledHeader bool // handler accessed handlerHeader via Header // 对应字符串长度 written int64 // number of bytes written in body contentLength int64 // explicitly-declared Content-Length; or -1 // 状态码 status int // status code passed to WriteHeader closeAfterReply bool requestBodyLimitHit bool trailers []string handlerDone atomicBool // set true when the handler exits dateBuf [len(TimeFormat)]byte clenBuf [10]byte statusBuf [3]byte closeNotifyCh chan bool didCloseNotify int32 // atomic (only 0->1 winner should send) } func (w *response) Header() Header { func (w *response) Write(data []byte) (n int, err error) { func (w *response) WriteHeader(code int) { ~~~ Client.go: --------- 客户端可以直接使用http.Get, http.Post等,示例如下: ~~~ package main import "net/http" import "fmt" import "io/ioutil" func main() { resp, err := http.Get("http://www.163.com") if err != nil { fmt.Println(err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ~~~ ~~~ func Get(url string) (resp *Response, err error) { func Post(url string, contentType string, body io.Reader) (resp *Response, err error) { func PostForm(url string, data url.Values) (resp *Response, err error) { func Head(url string) (resp *Response, err error) { func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, didTimeout func() bool, err error) { // 可以通过创建Client来做某些控制 type Client struct { Transport RoundTripper CheckRedirect func(req *Request, via []*Request) error Jar CookieJar Timeout time.Duration } func (c *Client) Get(url string) (resp *Response, err error) { func (c *Client) Post(url string, contentType string, body io.Reader) (resp *Response, err error) { func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) { func (c *Client) Head(url string) (resp *Response, err error) { func (c *Client) Do(req *Request) (*Response, error) { func (c *Client) send(req *Request, deadline time.Time) (resp *Response, didTimeout func() bool, err error) { ~~~ Request.go ---------- ~~~ type Request struct { Method string URL *url.URL Proto string // "HTTP/1.0" ProtoMajor int // 1 ProtoMinor int // 0 Header Header Body io.ReadCloser GetBody func() (io.ReadCloser, error) ContentLength int64 TransferEncoding []string Close bool Host string Form url.Values PostForm url.Values MultipartForm *multipart.Form Trailer Header RemoteAddr string RequestURI string TLS *tls.ConnectionState Cancel <-chan struct{} Response *Response ctx context.Context } func NewRequest(method, url string, body io.Reader) (*Request, error) { func (r *Request) Context() context.Context { func (r *Request) WithContext(ctx context.Context) *Request { func (r *Request) ProtoAtLeast(major, minor int) bool { func (r *Request) UserAgent() string { func (r *Request) Cookies() []*Cookie { func (r *Request) Cookie(name string) (*Cookie, error) { func (r *Request) AddCookie(c *Cookie) { func (r *Request) Referer() string { func (r *Request) MultipartReader() (*multipart.Reader, error) { func (r *Request) multipartReader() (*multipart.Reader, error) { func (r *Request) isH2Upgrade() bool { func (r *Request) Write(w io.Writer) error { func (r *Request) WriteProxy(w io.Writer) error { func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitForContinue func() bool) (err error) { func (r *Request) BasicAuth() (username, password string, ok bool) { func (r *Request) SetBasicAuth(username, password string) { func (r *Request) ParseForm() error { func (r *Request) ParseMultipartForm(maxMemory int64) error { func (r *Request) FormValue(key string) string { func (r *Request) PostFormValue(key string) string { func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) { func (r *Request) expectsContinue() bool { func (r *Request) wantsHttp10KeepAlive() bool { func (r *Request) wantsClose() bool { func (r *Request) closeBody() { func (r *Request) isReplayable() bool { func (r *Request) outgoingLength() int64 { ~~~ Response.go ----------- ~~~ type Response struct { Status string // e.g. "200 OK" StatusCode int // e.g. 200 Proto string // e.g. "HTTP/1.0" ProtoMajor int // e.g. 1 ProtoMinor int // e.g. 0 Header Header Body io.ReadCloser ContentLength int64 TransferEncoding []string Close bool Uncompressed bool Trailer Header Request *Request TLS *tls.ConnectionState } func (r *Response) Cookies() []*Cookie { func (r *Response) Location() (*url.URL, error) { func (r *Response) ProtoAtLeast(major, minor int) bool { func (r *Response) Write(w io.Writer) error { func (r *Response) closeBody() { func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) { ~~~

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1369 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传