
Lima tahun yang lalu saya mulai
mengembangkan Gophish , yang memungkinkan untuk belajar Golang. Saya menyadari bahwa Go adalah bahasa yang kuat, kemampuan yang dilengkapi oleh banyak perpustakaan. Go bersifat universal: khususnya, dengan bantuannya adalah mungkin untuk mengembangkan aplikasi server tanpa masalah.
Artikel ini adalah tentang menulis server di Go. Mari kita mulai dengan hal-hal sederhana, seperti "Halo dunia!", Dan akhiri dengan aplikasi dengan fitur berikut:
- Menggunakan Let's Encrypt untuk HTTPS.
- Bekerja sebagai router API.
- Bekerja dengan middleware.
- Pemrosesan file statis.
- Pematian yang benar.
Skillbox merekomendasikan: Pengembang Python dari awal tentu saja.
Kami mengingatkan Anda: untuk semua pembaca "Habr" - diskon 10.000 rubel saat mendaftar untuk kursus Skillbox apa pun menggunakan kode promo "Habr".
Halo dunia!
Membuat server web on Go sangat cepat. Berikut adalah contoh menggunakan pawang yang mengembalikan "Halo, dunia!" Dijanjikan di atas.
package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") }) http.ListenAndServe(":80", nil) }
Setelah itu, jika Anda memulai aplikasi dan membuka halaman
localhost , Anda akan segera melihat teks "Halo, dunia!" (tentu saja, jika semuanya berfungsi dengan benar).
Selanjutnya, kita akan berulang kali menggunakan handler, tetapi pertama-tama, mari kita pahami bagaimana semuanya berjalan.
net / http
Contohnya menggunakan paket
net/http
, yang merupakan alat utama di Go untuk mengembangkan kedua server dan klien HTTP. Untuk memahami kode ini, mari kita lihat makna dari tiga elemen penting: http.Handler, http.ServeMux dan http.Server.
Penangan HTTP
Ketika kami menerima permintaan, pawang menganalisanya dan membentuk respons. Go handler diimplementasikan sebagai berikut:
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
Contoh pertama menggunakan fungsi pembantu http.HandleFunc. Itu membungkus fungsi lain, yang pada gilirannya menerima http.ResponseWriter dan http.Request di ServeHTTP.
Dengan kata lain, penangan Golang diwakili oleh satu antarmuka, yang menyediakan banyak peluang bagi programmer. Jadi, misalnya, middleware diimplementasikan menggunakan handler, di mana ServeHTTP pertama kali melakukan sesuatu, dan kemudian memanggil metode ServeHTTP dari handler lain.
Seperti disebutkan di atas, penangan hanya menghasilkan tanggapan terhadap permintaan. Tetapi pawang mana yang harus digunakan pada titik waktu tertentu?
Meminta Routing
Untuk membuat pilihan yang tepat, gunakan multiplexer HTTP. Ini disebut muxer atau router di sejumlah perpustakaan, tetapi semuanya sama. Fungsi multiplexer adalah untuk menganalisis jalur permintaan dan memilih penangan yang sesuai.
Jika Anda memerlukan dukungan untuk perutean yang rumit, maka lebih baik menggunakan perpustakaan pihak ketiga. Salah satu yang paling canggih adalah
gorilla / mux dan
go-chi / chi , perpustakaan ini memungkinkan untuk mengimplementasikan pemrosesan perantara tanpa masalah. Dengan bantuan mereka, Anda dapat mengonfigurasi perutean wildcard dan melakukan sejumlah tugas lainnya. Nilai tambah mereka adalah kompatibilitas dengan penangan HTTP standar. Hasilnya, Anda dapat menulis kode sederhana dengan kemungkinan modifikasinya di masa mendatang.
Bekerja dengan kerangka kerja kompleks dalam situasi normal tidak memerlukan solusi standar, dan ini sangat mempersulit penggunaan penangan default. Untuk membuat sebagian besar aplikasi, kombinasi dari perpustakaan default dan router sederhana sudah cukup.
Meminta pemrosesan
Selain itu, kita memerlukan komponen yang akan "mendengarkan" koneksi yang masuk dan mengalihkan semua permintaan ke penangan yang benar. Tugas ini dapat dengan mudah dilakukan oleh http.Server.
Berikut ini menunjukkan bahwa server bertanggung jawab untuk semua tugas yang terkait dengan pemrosesan koneksi. Ini, misalnya, bekerja pada protokol TLS. Untuk menerapkan panggilan http.ListenAndServer, server HTTP standar digunakan.
Sekarang mari kita lihat contoh yang lebih kompleks.
Menambahkan Let's Encrypt
Secara default, aplikasi kami menggunakan protokol HTTP, tetapi disarankan untuk menggunakan protokol HTTPS. Dalam Go, ini bisa dilakukan tanpa masalah. Jika Anda menerima sertifikat dan kunci pribadi, maka cukup daftarkan ListenAndServeTLS dengan sertifikat dan file kunci yang benar.
http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)
Anda selalu bisa melakukan yang lebih baik.
Let's Encrypt memberikan sertifikat gratis dengan kemampuan untuk memperbarui secara otomatis. Untuk menggunakan layanan ini, Anda memerlukan paket
autocert
.
Cara termudah untuk mengkonfigurasinya adalah dengan menggunakan metode autocert.NewListener dalam kombinasi dengan http.Serve. Metode ini memungkinkan Anda untuk menerima dan memperbarui sertifikat TLS, sementara server HTTP memproses permintaan:
http.Serve(autocert.NewListener("example.com"), nil)
Jika kami membuka
example.com di browser, kami mendapat respons HTTPS "Halo, dunia!".
Jika Anda memerlukan konfigurasi yang lebih menyeluruh, maka Anda harus menggunakan manajer autocert.Manager. Kemudian kita membuat instance http.Server kita sendiri (sampai sekarang kita menggunakannya secara default) dan menambahkan manajer ke server TLSConfig:
m := &autocert.Manager{ Cache: autocert.DirCache("golang-autocert"), Prompt: autocert.AcceptTOS, HostPolicy: autocert.HostWhitelist("example.org", "www.example.org"), } server := &http.Server{ Addr: ":443", TLSConfig: m.TLSConfig(), } server.ListenAndServeTLS("", "")
Ini adalah cara mudah untuk menerapkan dukungan HTTPS penuh dengan pembaruan sertifikat otomatis.
Menambahkan rute khusus
Router default yang termasuk dalam pustaka standar baik, tetapi sangat sederhana. Sebagian besar aplikasi memerlukan perutean yang lebih kompleks, termasuk rute bersarang dan wildcard, atau prosedur untuk mengatur pola dan parameter jalur.
Dalam hal ini, Anda harus menggunakan paket
gorilla / mux dan
go-chi / chi . Kami akan belajar untuk bekerja dengan yang terakhir - contoh ditunjukkan di bawah ini.
Diberikan adalah file api / v1 / api.go yang berisi rute untuk API kami:
/ HelloResponse is the JSON representation for a customized message type HelloResponse struct { Message string `json:"message"` }
Kami menetapkan awalan api / vq untuk rute di file utama.
Kita kemudian dapat memasang ini ke router utama kita di bawah awalan api / v1 / di aplikasi utama kita:
Kesederhanaan bekerja dengan rute kompleks di Go memungkinkan penyederhanaan penyederhanaan dengan melayani aplikasi rumit yang besar.
Bekerja dengan middleware
Dalam hal pemrosesan antara, digunakan membungkus satu penangan HTTP dengan yang lain, yang memungkinkan untuk mengotentikasi, mengompres, jurnal, dan beberapa fungsi lainnya dengan cepat.
Sebagai contoh, perhatikan antarmuka http.Handler, dengan bantuannya kami menulis handler dengan otentikasi pengguna layanan.
func RequireAuthentication(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !isAuthenticated(r) { http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) return }
Ada router pihak ketiga, misalnya, chi, yang memungkinkan Anda untuk memperluas fungsi pemrosesan perantara.
Bekerja dengan file statis
Pustaka Go standar mencakup fitur untuk bekerja dengan konten statis, termasuk gambar, serta file JavaScript dan CSS. Mereka dapat diakses melalui fungsi http.FileServer. Ini mengembalikan penangan yang mendistribusikan file dari direktori tertentu.
func NewRouter() http.Handler { router := chi.NewRouter() r.Get("/{name}", HelloName)
Perlu diingat bahwa http.Dir menampilkan konten direktori jika tidak memiliki file index.html utama. Dalam hal ini, untuk mencegah direktori tidak disusupi, ada baiknya menggunakan paket yang tidak
unindexed
.
Pematian yang benar
Go juga memiliki fitur seperti mematikan server HTTP dengan benar. Ini dapat dilakukan dengan menggunakan metode Shutdown (). Server mulai di goroutine, dan kemudian saluran didengarkan untuk menerima sinyal interupsi. Segera setelah sinyal diterima, server dimatikan, tetapi tidak segera, tetapi setelah beberapa detik.
handler := server.NewRouter() srv := &http.Server{ Handler: handler, } go func() { srv.Serve(autocert.NewListener(domains...)) }()
Kesimpulannya
Go adalah bahasa yang kuat dengan perpustakaan standar yang hampir universal. Kemampuan standarnya sangat luas, dan Anda dapat memperkuatnya dengan bantuan antarmuka - ini memungkinkan Anda untuk mengembangkan server HTTP yang benar-benar andal.
Skillbox merekomendasikan: