HTTP Server for golang-net/http source analysis

Source: Internet
Author: User

This article Csdn blog links: http://blog.csdn.net/screscent/article/details/53583764
This article QQ space link: http://user.qzone.qq.com/29185807/blog/1481529299 golang-net/http Source Code Analysis of HTTP Server 1 Introduction

Look at the example in the Net/http library first

To create an HTTP server, just a few simple statements.

    http. Handle ("/foo", Foohandler)

    http. Handlefunc ("/bar", func (w http). Responsewriter, R *http. Request) {
        fmt. fprintf (W, "Hello,%q", HTML.) Escapestring (R.url. Path)
    })

    log. Fatal (http. Listenandserve (": 8080", nil))

The interface section is as follows

    Type Handlerfunc func (Responsewriter, *request)
2 Routing

To understand HTTP server, you should start with routing. So start looking at the source

        Type servemux struct {
            mu    sync. Rwmutex
            m     map[string]muxentry
            hosts bool//whether any patterns contain hostnames
        }

        type Muxentry struct {
            explicit bool
            h        Handler
            pattern  string
        }

        //Newservemux allocates and Returns a new Servemux.
        Func Newservemux () *servemux {return new (SERVEMUX)}

        //Defaultservemux are the default Servemux used by Serve.
        var Defaultservemux = &defaultservemux

        

Servermux is an HTTP routing struct. The map inside contains a routing hash table.

In addition, the above code also forms a Defaultservemux, the default routing object.

    Type Servemux
        func newservemux () *servemux
        func (mux *servemux) Handle (pattern string, handler handler)
        Func (Mux *servemux) Handlefunc (pattern string, handler func (Responsewriter, *request))
        func (Mux *servemux) handler (R *request) (H Handler, pattern string)
        Func (Mux *servemux) servehttp (w responsewriter, R *request)

The following one to do function Analysis 2.1 Handle

    Func (Mux *servemux) Handle (pattern string, handler handler)

This function is to register the routing table function, the function is to create the muxentry, and then put it into the routing map

    Func (Mux *servemux) Handle (pattern string, handler handler) {Mux.mu.Lock () defer Mux.mu.Unlo CK () if pattern = = "" {Panic ("http:invalid pattern" + pattern)} I
                F handler = = nil {Panic ("Http:nil handler")} if mux.m[pattern].explicit {
                Panic ("Http:multiple registrations for" + pattern)} if mux.m = = Nil { MUX.M = Make (Map[string]muxentry)}//main place is here mux.m[pattern] = Muxentry{explici

            T:true, H:handler, Pattern:pattern} if pattern[0]!= '/' {mux.hosts = true}
            Helpful behavior://If is/tree/, insert an implicit permanent redirect.
            It can be overridden by a explicit registration. N: = Len (pattern) if n > 0 && pattern[n-1] = = '/' &&!mux.m[pattern[0:n-1]].explicit {//If contains a host name, strip it and use remain
                ing//path for redirect.  Path: = Pattern if pattern[0]!= '/' {//in pattern, at least the last character is a '/', so//strings.
                    Index can ' t be-1. Path = pattern[strings. Index (Pattern, "/"):]} URL: = &url. Url{path:path} mux.m[pattern[0:n-1] = Muxentry{h:redirecthandler (URL. String (), statusmovedpermanently), Pattern:pattern}}}
2.2 Handlefunc

Handlefunc is the encapsulation of handle.

    Func (Mux *servemux) Handlefunc (pattern string, handler func (Responsewriter, *request)) {
        mux. Handle (Pattern, Handlerfunc (handler))
    }
2.3 Handler

Handler is based on the access path of request, find the related routing table, get the processing function

        Func (Mux *servemux) Handler (R *request) (H Handler, pattern string) {if R.method!= "CONNECT" { If p: = CleanPath (R.url. Path); P!= R.url. Path {_, pattern = Mux.handler (r.host, p) URL: = *r.url url.p Ath = P return redirecthandler (URL. String (), statusmovedpermanently), pattern}} return Mux.handler (R.host, R.URL.P ATH)} func (Mux *servemux) handler (host, path string) (H handler, pattern string) {mux.mu.
            Rlock () defer mux.mu.RUnlock ()//Host-specific pattern takes precedence over generic ones
                If mux.hosts {h, pattern = mux.match (host + Path)} if H = = Nil { H, pattern = Mux.match (path)} if H = nil {h, pattern = Notfoundhandler () , ""} Return
        } 
2.4 servehttp

Serverhttp is the gateway to the route.

    Func (Mux *servemux) servehttp (w responsewriter, R *request) {
    //Below is the process URL path
        If R.requesturi = "*" {
            if R.prot Oatleast (1, 1) {
                w.header (). Set ("Connection", "Close")
            }
            W.writeheader (statusbadrequest)
            return
        }
        //Find Handler
        H, _ : = Mux. Handler (R)
        //Specific processing
        h.servehttp (W, R)
    }
2.5 Defaultservemux

Default route, just a layer of DEFAULTSERVEMUX encapsulation

        Func Handle (pattern string, handler handler) {Defaultservemux.handle (pattern, handler)}
        func Handlefunc (pattern String, handler func (Responsewriter, *request)) {
                Defaultservemux.handlefunc (pattern, handler)
            }
3 Server

Portal, creating and listening.

is actually creating a server object

        Func listenandserve (addr string, handler handler) error {
            server: = &server{addr:addr, handler:handler}
            ret Urn server. Listenandserve ()
        }

Look at what the server has to offer

    Type Server
        func (SRV *server) listenandserve () Error
        func (SRV *server) listenandservetls (CertFile, keyfile String) Error
        func (SRV *server) Serve (l net. Listener) Error
        func (SRV *server) setkeepalivesenabled (v bool)

Below we trace the process 3.1 listenandserve

        Func (SRV *server) listenandserve () error {
            addr: = srv. Addr
            If Addr = = "" {
                Addr = ": http"
            }
            ln, err: = Net. Listen ("tcp", addr)
            If Err!= nil {return
                err
            } return
            srv. Serve (Tcpkeepalivelistener{ln. ( *net. TcpListener)})
        }

Where listen returns a listener interface.

        Func Listen (NET, laddr string) (Listener, error)

        type Listener interface {
            //Accept waits for and returns the N Ext connection to the listener.
            Accept () (Conn, error)

            //close closes the listener.
            Any blocked Accept operations is unblocked and return errors.
            Close () error

            //ADDR Returns the listener's network address.
            ADDR () Addr
    }
3.2 Serve

The real entrance.

Step: Accept–>srv.newconn–>c.serve (CTX)

        Func (SRV *server) Serve (l net. Listener) Error {defer l.close () if fn: = Testhookserverserve; fn!= nil {fn (SRV , L)} var tempdelay time. Duration//How long to sleep on accept failure If err: = Srv.setuphttp2_serve (); Err!= nil {return err}//Todo:allow changing base context?
            Can ' t imagine concrete//use cases yet. Basectx: = Context. Background () CTX: = Context. Withvalue (Basectx, Servercontextkey, srv) CTX = context. Withvalue (CTX, Localaddrcontextkey, L.addr ()) for {//Call Accept listener RW, e: = l.accept () if E!= nil {if NE, ok: = e. Net. ERROR); Ok && ne. Temporary () {if Tempdelay = 0 {tempdelay = 5 * time.
                         Millisecond} else {   Tempdelay *= 2} if Max: = 1 * time. Second; Tempdelay > Max {tempdelay = max} srv.log F ("Http:accept error:%v; Retrying in%v ", E, Tempdelay) time.
                Sleep (Tempdelay) Continue} return E}  Tempdelay = 0//Get new link c: = Srv.newconn (rw) c.setstate (C.RWC, statenew)//Before Serve can return//link processing place go c.serve (CTX)}}
4 Conn 4.1 newconn

CREATED a conn

        Func (SRV *server) newconn (RWC net. Conn) *conn {
            c: = &conn{
                server:srv,
                RWC:    RWC,
            }
            if debugserverconnections {
                C.RWC = Newloggingconn ("Server", C.RWC)
            } return
            c
        }
4.2 Serve

Read the data in the Conn and then process it.

    Serve a new connection.
    Func (c *conn) serve (CTX context. Context) {
        c.remoteaddr = c.rwc.remoteaddr (). String () ...
        C.R = &CONNREADER{R:C.RWC}
        c.bufr = Newbufioreader (C.R)
        C.BUFW = Newbufiowritersize (checkconnerrorwriter {c}, 4<<10)

        ctx, Cancelctx: = context. Withcancel (CTX)
        defer cancelctx ()

        for {
            W, err: = C.readrequest (CTX)

            ...
            The real processing place
            Serverhandler{c.server}. Servehttp (W, w.req)
            w.cancelctx ()
            if c.hijacked () {
                return
            }
            w.finishrequest ()
            if! W.shouldreuseconnection () {
                if W.requestbodylimithit | | w.closedrequestbodyearly () {
                    c.closewriteandwait ( )
                }
                return
            }
            c.setstate (C.RWC, Stateidle)
        }
    }
4.3 servehttp

The final place. By looking for routes, find the route handler function, and then respond to the request information.

    Type Serverhandler struct {
        srv *server
    }

    func (Sh serverhandler) servehttp (rw responsewriter, req *request) {
        Handler: = Sh.srv.Handler
        //nil uses the default route
        if handler = = Nil {
            handler = Defaultservemux
        }
        if Req. RequestUri = "*" && req. method = = "Options" {
            handler = globaloptionshandler{}
        }
        handler. Servehttp (rw, req)
    }
5 SummaryRouting section, build a map to store the routing processing Function link processing part, constructs a TCP listener, then accept, constructs the Conn then through Conn, looks for the route, locates the processing function, carries on the processing

Hao Haohua
QQ 29185807 Crescent moon-Dao Chang
December 12, 2016

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.