พื้นฐานของ HTTP 서버ของ 패키지 net/http

18153 단어 gohttp
세트 net/http นั้นออกแบบให้เราสร้าง HTTP 서버ขึ้นมาได้โดยสร้าง 타입ที่ชื่อว่า 서버เพื่อเก็บค่าต่างๆของ 서버แล้วก็มี 메서드ชื่อ ListendServให้เรา 서버 시작พร้อมกับกำหนด 처리자เพื่อทำงานเมื่อมี 청원เข้ามานั้นเอง
นี่คือ 유형 서버ซึ่งเป็น 구조ที่มี 영역ต่างๆไว้กำหนดรายละเอียดของ 서버ซึ่งเบื้องต้นที่จำเป็นก็คือ 소재지ไว้กำหนด TCP 주소(호스트 이름: 포트)แล้วก็ 처리자ไว้กำหนด 처리자ที่จะทำงานเมื่อมี 청원เข้ามา
type Server struct {
    // Addr optionally specifies the TCP address for the server to listen on,
    // in the form "host:port". If empty, ":http" (port 80) is used.
    // The service names are defined in RFC 6335 and assigned by IANA.
    // See net.Dial for details of the address format.
    Addr string

    Handler Handler // handler to invoke, http.DefaultServeMux if nil

    // TLSConfig optionally provides a TLS configuration for use
    // by ServeTLS and ListenAndServeTLS. Note that this value is
    // cloned by ServeTLS and ListenAndServeTLS, so it's not
    // possible to modify the configuration with methods like
    // tls.Config.SetSessionTicketKeys. To use
    // SetSessionTicketKeys, use Server.Serve with a TLS Listener
    // instead.
    TLSConfig *tls.Config

    // ReadTimeout is the maximum duration for reading the entire
    // request, including the body.
    //
    // Because ReadTimeout does not let Handlers make per-request
    // decisions on each request body's acceptable deadline or
    // upload rate, most users will prefer to use
    // ReadHeaderTimeout. It is valid to use them both.
    ReadTimeout time.Duration

    // ReadHeaderTimeout is the amount of time allowed to read
    // request headers. The connection's read deadline is reset
    // after reading the headers and the Handler can decide what
    // is considered too slow for the body. If ReadHeaderTimeout
    // is zero, the value of ReadTimeout is used. If both are
    // zero, there is no timeout.
    ReadHeaderTimeout time.Duration

    // WriteTimeout is the maximum duration before timing out
    // writes of the response. It is reset whenever a new
    // request's header is read. Like ReadTimeout, it does not
    // let Handlers make decisions on a per-request basis.
    WriteTimeout time.Duration

    // IdleTimeout is the maximum amount of time to wait for the
    // next request when keep-alives are enabled. If IdleTimeout
    // is zero, the value of ReadTimeout is used. If both are
    // zero, there is no timeout.
    IdleTimeout time.Duration

    // MaxHeaderBytes controls the maximum number of bytes the
    // server will read parsing the request header's keys and
    // values, including the request line. It does not limit the
    // size of the request body.
    // If zero, DefaultMaxHeaderBytes is used.
    MaxHeaderBytes int

    // TLSNextProto optionally specifies a function to take over
    // ownership of the provided TLS connection when an ALPN
    // protocol upgrade has occurred. The map key is the protocol
    // name negotiated. The Handler argument should be used to
    // handle HTTP requests and will initialize the Request's TLS
    // and RemoteAddr if not already set. The connection is
    // automatically closed when the function returns.
    // If TLSNextProto is not nil, HTTP/2 support is not enabled
    // automatically.
    TLSNextProto map[string]func(*Server, *tls.Conn, Handler)

    // ConnState specifies an optional callback function that is
    // called when a client connection changes state. See the
    // ConnState type and associated constants for details.
    ConnState func(net.Conn, ConnState)

    // ErrorLog specifies an optional logger for errors accepting
    // connections, unexpected behavior from handlers, and
    // underlying FileSystem errors.
    // If nil, logging is done via the log package's standard logger.
    ErrorLog *log.Logger

    // BaseContext optionally specifies a function that returns
    // the base context for incoming requests on this server.
    // The provided Listener is the specific Listener that's
    // about to start accepting requests.
    // If BaseContext is nil, the default is context.Background().
    // If non-nil, it must return a non-nil context.
    BaseContext func(net.Listener) context.Context

    // ConnContext optionally specifies a function that modifies
    // the context used for a new connection c. The provided ctx
    // is derived from the base context and has a ServerContextKey
    // value.
    ConnContext func(ctx context.Context, c net.Conn) context.Context
    // contains filtered or unexported fields
}
ส่วน 처리자นั้นจริงๆแล้วเป็น 이음매หน้าตาแบบนี้
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}
นั่นคือเราจะสร้าง 타입อะไรก็ได้ขอให้ 구현 방법 ServeHTTPตรงกับที่ 인터페이스 프로세서กำหนดก็พอก็สามารถกำหนดให้กับ 서버ได้แล้ว
ทีนี้มาดูโค้ดที่ใช้ HTTP 서버 시작ด้วย 8000 포트สำหรับรับ HTTP 요청เบื้องต้นกัน
package main

import (
    "log"
    "net/http"
)

type handler struct{}

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, World\n"))
}

func main() {
    server := http.Server{
        Addr:    ":8000",
        Handler: &handler{},
    }
    err := server.ListenAndServe()
    if err != nil {
        log.Fatal(err)
    }
}
ลองเปิด 브라우저แล้วเข้าไปที่ 로컬 호스트: 8000จะเจอ Hello, World แบบนี้

นี่คือโครงสร้างเบื้องต้นที่ 세트net/httpถูกออกแบบเอาไว้เลย แต่ที่เราใช้งานแล้วสะดวกกว่านี้เพราะตัว 싸다เองนั้นได้เตรียม 처리자ที่ใช้ง่ายกว่านี้เอาไว้ให้แล้วนั่นเองเช่น ที่เราใช้กันบ่อยๆโดยอาจจะไม่รู้ตัวนั่นคือ HandlerFunc , ServeMux เพราะ 기능อย่าง http.HandleFunc กับ http.Handle มันจัดการให้เราเองไปแล้ว โดยทุกครั้งที่เราใช้สองฟังก์ชันนี้มันจะใช้ DefaultServeMux นั่นเอง
ทีนี้มาดูว่าถ้าเราจะไม่ใช้ 약속을 어기다แล้วสร้าง ServeMux เองจะเป็นยังไง ตัวอย่างโค้ดที่ใช้ ServeMux เองเป็นแบบนี้
package main

import (
    "log"
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, World\n"))
    })
    server := http.Server{
        Addr:    ":8000",
        Handler: mux,
    }
    err := server.ListenAndServe()
    if err != nil {
        log.Fatal(err)
    }
}
ลองดูโค้ด 메서드ของ HandleFunc ของ ServeMux หน้าตาเป็นแบบนี้
// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    if handler == nil {
        panic("http: nil handler")
    }
    mux.Handle(pattern, HandlerFunc(handler))
}
นั่นคือเอาฟังก์ชันที่เราส่งไปแปลงเป็น 유형HandlerFuncที่ก็ยัง 인터페이스 프로세서 구현เอาไว้นั่นเอง แล้วส่งต่อไปเรีย mux.Handle ซึ่งจะเก็บข้อมูลว่า 도안ไหนจะเรียก 처리자ตัวไหนเอาไว้ เมื่อมี 청원เข้ามาก็จะเรียก 메서드 ServeHTTPของ ServeMux เพื่อแกะ 요청 경로แล้วเรียก 처리자ที่ 등기부ไว้อีกที
ส่วน 유형HandlerFuncนั้นหน้าตาเป็นแบบนี้ และ 실현 처리 프로그램เอาไว้ง่ายๆเลยแบบนี้
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}
นั่นคือตัวมันเองเป็น 기능ดังนั้นเมื่อ ServeHTTP 구현ก็เอา 인수 변수ที่เป็นฟังก์ชันนั่นเองเรียกต่อไปได้เลย

ขอฝาก 커피 한 잔 주세요.


สำหรับท่านใดที่อ่านแล้วชอบโพสต์ต่างๆของผมที่นี่ ต้องการสนับสนุนค่ากาแฟเล็กๆน้อยๆ สามารถสนับสนุนผมได้ผ่านทาง 커피 한 잔 주세요.คลิ๊กที่รูปด้านล่างนี้ได้เลยครับ

ส่วนท่านใดไม่สะดวกใช้บัตรเครดิต หรือ 패보สามารถสนับสนุนผมได้ผ่านทาง 선불금โดยดู QR코드ได้จากโพสต์ที่พินเอาไว้ได้ที่ 페이지 디자인ครับ https://web.facebook.com/devdoseth
ขอบคุณครับ 🙏

좋은 웹페이지 즐겨찾기