asm_amd64.s
TEXT runtime·goexit(SB),NOSPLIT,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return
// traceback from goexit1 must hit code range of goexit
BYTE $0x90 // NOP
runtime-> asm_amd64.s->net/http/server.go:1739
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
c.remoteAddr = c.rwc.RemoteAddr().String()
......
c.r = &connReader{conn: c}
c.bufr = newBufioReader(c.r)
c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
for {
w, err := c.readRequest(ctx)
if c.r.remain != c.server.initialReadLimitSize() {
// If we read any bytes off the wire, we're active.
c.setState(c.rwc, StateActive)
}
.....
serverHandler{c.server}.ServeHTTP(w, w.req)//先构造一个server,调用开始
w.cancelCtx()
if c.hijacked() {
return
}
....
2.调用ServeHTTP
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler//获取server
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {//判断是否为跨域访问
handler = globalOptionsHandler{}
}
handler.ServeHTTP(rw, req)
}
reflect/value.go
func (v Value) call(op string, in []Value) []Value {
// Get function pointer, type.
......
call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
// For testing; see TestCallMethodJump.
if callGC {
runtime.GC()
}
......
asm_amd64.s
TEXT reflect·call(SB), NOSPLIT, $0-0
JMP ·reflectcall(SB)
micro/h2c/h2c.go
// ServeHTTP will serve with an HTTP/2 connection if possible using the `H2Server`.
// The request will be handled by the wrapped `Handler` in any case.
func (h *HandlerH2C) ServeHTTP(
w http.ResponseWriter,
req *http.Request) {
// HTTP/2 With Prior Knowledge
if req.Method == "PRI" && req.URL.Path == "*" && req.ProtoMajor == 2 {
// log.Debugf("Attempting h2c with prior knowledge.")
conn, err := initH2CWithPriorKnowledge(w)
if err != nil {
// log.Debugf("Error h2c with prior knowledge: %v", err)
return
}
defer conn.Close()
h2cSrv := &http2.Server{}
h2cSrv.ServeConn(conn, &http2.ServeConnOpts{Handler: h.Handler})
return
}
// HTTP/2 Upgrade
if conn, err := h2cUpgrade(w, req); err == nil {
defer conn.Close()
h2cSrv := &http2.Server{}
h2cSrv.ServeConn(conn, &http2.ServeConnOpts{Handler: h.Handler})
return
}
// Everything else
h.Handler.ServeHTTP(w, req)
}
micro/go-micro/server/rpc-server.go
// ServeConn serves a single connection
func (s *rpcServer) ServeConn(sock transport.Socket) {
defer func() {
// close socket
sock.Close()
...
...
// create a wrapped function
handler := func(ctx context.Context, req Request, rsp interface{}) error {
return r.**ServeRequest**(ctx, req, rsp.(Response))
}
for i := len(s.opts.HdlrWrappers); i > 0; i-- {
handler = s.opts.HdlrWrappers[i-1](handler)
}
// TODO: handle error better
if err := handler(ctx, request, response); err != nil {
// write an error response
err = rcodec.Write(&codec.Message{
Header: msg.Header,
Error: err.Error(),
Type: codec.Error,
}, nil)
// could not write the error response
if err != nil {
log.Logf("rpc: unable to write error response: %v", err)
}
s.wg.Done()
return
}
// done
s.wg.Done()
}
}
net/http/server.go
// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
micro/go-micro/transport/http-transport.go
func (h *httpTransportListener) Accept(fn func(Socket)) error {
// create handler mux
mux := http.NewServeMux()
// register our transport handler
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var buf *bufio.ReadWriter
var con net.Conn
// read a regular request
if r.ProtoMajor == 1 {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
r.Body = ioutil.NopCloser(bytes.NewReader(b))
// hijack the conn
hj, ok := w.(http.Hijacker)
if !ok {
// we're screwed
http.Error(w, "cannot serve conn", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
buf = bufrw
con = conn
}
// save the request
ch := make(chan *http.Request, 1)
ch <- r
fn(&httpTransportSocket{
ht: h.ht,
w: w,
r: r,
rw: buf,
ch: ch,
conn: con,
local: h.Addr(),
remote: r.RemoteAddr,
})
})
// get optional handlers
if h.ht.opts.Context != nil {
handlers, ok := h.ht.opts.Context.Value("http_handlers").(map[string]http.Handler)
if ok {
for pattern, handler := range handlers {
mux.Handle(pattern, handler)
}
}
}
// default http2 server
srv := &http.Server{
Handler: mux,
}
// insecure connection use h2c
if !(h.ht.opts.Secure || h.ht.opts.TLSConfig != nil) {
srv.Handler = &h2c.HandlerH2C{
Handler: mux,
H2Server: &http2.Server{},
}
}
// begin serving
return srv.Serve(h.listener)
}
micro/go-micro/server/rpc-router.go
func (router *router) ServeRequest(ctx context.Context, r Request, rsp Response) error {
sending := new(sync.Mutex)
service, mtype, req, argv, replyv, keepReading, err := router.readRequest(r)
log.Log("rpc_router==ServeRequest 打印 req=9=>>",req)
if err != nil {
if !keepReading {
return err
}
// send a response if we actually managed to read a header.
if req != nil {
router.freeRequest(req)
}
return err
}
return service.call(ctx, router, sending, mtype, req, argv, replyv, rsp.Codec())
}
micro/go-micro/server/rpc-server.go
func (s *rpcServer) Start() error {
registerDebugHandler(s)
config := s.Options()
// start listening on the transport
ts, err := config.Transport.Listen(config.Address)
if err != nil {
return err
}
...
...
go func() {
for {
// listen for connections
err := ts.Accept(s.ServeConn)
// TODO: listen for messages
// msg := broker.Exchange(service).Consume()
select {
// check if we're supposed to exit
case <-exit:
return
// check the error and backoff
default:
if err != nil {
log.Logf("Accept error: %v", err)
time.Sleep(time.Second)
continue
}
}
// no error just exit
return
}
}()
...
...
return nil
}