พื้นฐานของ HTTP 서버ของ 패키지 net/http
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
ขอบคุณครับ 🙏
Reference
이 문제에 관하여(พื้นฐานของ HTTP 서버ของ 패키지 net/http), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/iporsut/http-server-package-net-http-3kdn텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)