+1

Hiểu Trọn Bộ `net/http` Trong Golang

Đây là bài viết tổng hợp toàn bộ kiến thức nền tảng về net/http trước khi bạn tìm hiểu về ServeMux/router.
Nếu bạn đọc đến cuối mà không hiểu, hãy đổ lỗi cho… người gõ phím, không phải bạn.


Mục tiêu của bài blog

Sau bài này, bạn sẽ hiểu:

  • Handler interface thực chất là cái gì mà ai cũng nhắc.
  • Tại sao một kiểu dữ liệu nhìn ngố như type hotdog int lại có thể trở thành web server.
  • Request chứa những gì (spoiler: rất nhiều).
  • ResponseWriter là cái gì và vì sao nó có quyền năng gửi data về trình duyệt.
  • Form data đi vào đâu, tại sao phải ParseForm().
  • Preview nhỏ về ServeMux – router chính thức của Go.

1. Vũ trụ Go Web bắt đầu từ… Handler Interface

Chỉ một dòng:

ServeHTTP(w http.ResponseWriter, r *http.Request)

Bất kỳ type nào có method y chang dòng phía trên đều trở thành… Handler.

Ví dụ:

type hotdog int

func (h hotdog) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hotdog server is serving 🔥")
}

Từ giờ, hotdog trở thành server hợp lệ.

var d hotdog
http.ListenAndServe(":8080", d)

Bạn vừa chạy một web server… bằng hotdog.
Không đùa đâu.


2. ServeHTTP – Luật chơi của Web

Một server có 2 nhiệm vụ:

  1. Nhận request
  2. Trả response

Thế nên tham số của phương thức ServeHTTP vô cùng logic:

  • r *http.Request: thông tin mà client gửi lên
  • w http.ResponseWriter: nơi bạn ghi nội dung để trả về

Hết.


3. *http.Request — Kho báu dữ liệu người dùng gửi lên

Request là một struct rất lớn.
Nó có rất nhiều trường — đủ để viết tiểu thuyết 7 chương.

Những trường quan trọng bạn cần nhớ:

Method

r.Method  // GET, POST…

URL

r.URL.Path
r.URL.RawQuery

Header

r.Header.Get("User-Agent")

ContentLength

r.ContentLength

Form Data

Để lấy dữ liệu từ form, bạn phải:

r.ParseForm()

Sau đó:

r.Form      // map[string][]string — gồm cả URL query + POST body
r.PostForm  // chỉ từ POST body

Hoặc tiện hơn:

r.FormValue("fname") // trả về giá trị đầu tiên

4. URL Values – Kiểu dữ liệu "đa nhân cách"

Cả Form, PostForm, URL.Query() đều có kiểu:

map[string][]string

Tức là:

  • Key → tên biến
  • Value → slice chứa nhiều giá trị

Ví dụ người dùng submit 2 giá trị cho cùng 1 field:

fname=Todd&fname=James

Bạn sẽ nhận được:

map["fname"] = []string{"Todd", "James"}

Nhìn quen không?
Đúng, nó giống y hệt cách HTML hoạt động.


5. ResponseWriter — Ông vua trả dữ liệu về trình duyệt

ResponseWriter có ba “siêu năng lực”:

Đặt header

w.Header().Set("Content-Type", "text/html")

Gửi status code

w.WriteHeader(200)

Lưu ý: gọi WriteHeader trước khi ghi body.
Nếu không bạn sẽ gặp lỗi “header already written”.

Ghi body về client

fmt.Fprintln(w, "<h1>Hello World</h1>")

Thế là xong.


6. Tổng hợp: Một handler hoàn chỉnh sẽ trông như sau

type hotdog int

func (h hotdog) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()

    w.Header().Set("Content-Type", "text/html")

    fmt.Fprintln(w, "<h1>Information</h1>")
    fmt.Fprintf(w, "Method: %s<br>", r.Method)
    fmt.Fprintf(w, "URL Path: %s<br>", r.URL.Path)
    fmt.Fprintf(w, "Form values: %v<br>", r.Form)
}

Chạy:

var d hotdog
http.ListenAndServe(":8080", d)

7. Preview: ServeMux – Router "xịn" sắp xuất hiện

mux := http.NewServeMux()

mux.HandleFunc("/", home)
mux.HandleFunc("/about", about)

http.ListenAndServe(":8080", mux)

Lý do mux có thể truyền vào ListenAndServe?

Vì ServeMux… cũng implement:

ServeHTTP(w http.ResponseWriter, r *http.Request)

Nó cũng là Handler!

Cả thế giới Go Web xoay quanh đúng interface này.


8. Kết luận

Sau bài này, bạn phải nắm rõ:

  • Handler interface = vua của web server trong Go.
  • Request chứa rất nhiều dữ liệu hữu ích.
  • ResponseWriter là cách bạn “nói chuyện” với browser.
  • ParseForm là bắt buộc trước khi đọc form data.
  • Form → cả URL + body
    PostForm → chỉ body
  • ServeMux (router) cũng là Handler.

Bạn đã có 90% nền tảng để viết web server Go chuyên nghiệp.

Phần tiếp theo sẽ là cuộc cách mạng:
Routing, ServeMux, HandlerFunc, middleware…

Hứa hẹn rất thú vị.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí