[Go] Package http

Package http

net/http 패키지를 통해 HTTP 서버를 구현할 수 있다.

Table of Contents

HTTP Basic

HTTP 에 대해 더 자세히 알고자 한다면 HTTP에 대한 블로그 글 을 참고하자.

HTTP : HyperText Transfer Protocol
현재 전세계 대부분의 클라이언트와 서버는 HTTP 를 통해 통신한다.
HTTP는 HyperText들의 문서들을 주고 받는데 사용되는 프로토콜이다.

HTTP 용어 분석
HyperText → 하이퍼텍스트를 기반으로

Transfer → 데이터를 전송하는

Protocol → 통신 규약

Server 와 Client
Client & Server

Return to TOC

http 코드 열어보기

ResponseWriter

HTTP 응답을 위한 인터페이스, response 를 구성해준다.

type ResponseWriter interface {
  Header() Header
  Write([]byte) (int, error)
  WriteHeader(statusCode int)
}

Return to TOC

timeoutWriter

type timeoutWriter struct {
  w     ResponseWriter
  h     Header
  wbuf  bytes.Buffer
  req   *Request
  
  mu            sync.Mutex
  timeOut       bool
  wroteHeader   bool
  code          int
}

timeoutWriterResponseWriter 인터페이스와 Header 맵을 내장하고 있다.

WriterHeader

  func (tw *timeoutWriter) WriteHeader(code int) {
    tw.mu.Lock()
    defer tw.mu.Unlock()
    tw.writeHeaderLocked(code)
  }
func (tw *timeoutWriter) Header() Header { return tw.h }

Return to TOC

Handler

Handler 인터페이스는 응답 처리를 위해 사용된다.
Handler 는 서버가 클라이언트로 부터 요청을 받았을 때 그 요청을 핸들링 해준다.

type Handler interface {
  ServeHTTP(ResponseWriter, *Request)
}

Return to TOC

Flusher

Flush 는 buffered data 를 클라이언트에게 보낸다.

type Flusher interface {
  Flush()
}

Return to TOC

Hijacker

type Hijacker interface {
  Hijack() (net.Conn, *bufio.ReadWriter, error)
}

http.flush

func (cw *chunkWriter) flush() {
  if !cw.wroteHeader {
     cw.writeHeader(nil)
  }
  cw.res.conn.bufw.Flush()
}

Return to TOC

conn struct

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 
    curState   struct{ atomic uint64 } 
    mu         sync.Mutex
    hijackedv  bool
}

Return to TOC

http.ServeHTTP

ServeHTTP() 메서드는 응답시 데이터를 쓰기 위한 ResponseWriter 와 HTTP Request 입력 데이터를 파라미터로 갖는다.

func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
  Redirect(w, r, rh.url, rh.code)
}

http.RedirectHandler

func RedirectHandler(url string, code int) Handler {
  return &redirectHandler{url, code}
}

Return to TOC

http.Handler

func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {

  if r.Method == "CONNECT" {
     if u, ok := mux.redirectToPathSlash(r.URL.Host, r.URL.Path, r.URL); ok {
        return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
     }

     return mux.handler(r.Host, r.URL.Path)
  }

  host := stripHostPort(r.Host)
  path := cleanPath(r.URL.Path)

  if u, ok := mux.redirectToPathSlash(host, path, r.URL); ok {
     return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
  }

  if path != r.URL.Path {
     _, pattern = mux.handler(host, path)
     url := *r.URL
     url.Path = path
     return RedirectHandler(url.String(), StatusMovedPermanently), pattern
  }

  return mux.handler(host, r.URL.Path)
}

Return to TOC

http.HandleFunc

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  if handler == nil {
     panic("http: nil handler")
  }
  mux.Handle(pattern, HandlerFunc(handler))
}
s.Router.HandleFunc("/",middleware.MiddlewareJSON(handler.Home)).Methods("GET")

Return to TOC

http.ListenAndServe

ListenAndServe 는 웹 요청을 기다리고 있다가(listen) 요청이 들어오면 해당 요청을 처리(serve)한다.

func ListenAndServe(addr string, handler Handler) error {
  server := &Server{Addr: addr, Handler: handler}
  return server.ListenAndServe()
}

Return to TOC

http.ServeHTTP

요청한 http 메서드와 URL 을 토대로 합당한 핸들러를 찾아 동작시키는 메서드.

func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request)
    // .... 너무 길어 생략 ...
* 요청에 합당한 핸들러가 없을시 NotFound 에러가 리턴된다.