+4

[Golang] Dealing with the panic in your rest api.

Lời tựa

Xin chào, đến hẹn lại lên. Hôm nay, Thống xin được chia sẽ về cách xử lí panic trong rest api nhé. 😁😁

Bài toán

rest api -

Về kiến trúc mình sẽ dùng gin framework để support define rest api. Khi có 1 request được gửi đến, nó sẽ đi qua 3 tầng - transport -> service -> repo -> db library. (Và như mọi lần, mình sẽ để source ở đây và chỉ điểm mặt những ý chính để các bạn tiện theo dõi nhé).
Khi code golang, chắc hẳn bạn đã biết panic có thể stop "program" nếu nó ko được "recovered". Và để rest server không bị crashed thì bất cứ khi có 1 "panic" nào xãy ra ở trong quá trình call request, chúng ta phải sẽ catch được error và tiến hành recover lại.
Okee, trước khi fix được bug thì ít nhất ta phải thấy được bug cái đã.

Tiến hành trigger panic

Mình sẽ set up file ".env" và kích hoạt panic dưa theo file này:
image.png
Trigger panic ở db library:
image.png
image.png
Run server and see a run time error:
Server
image.png
Client response
image.png
Run time error đã xuất hiện , client thì nhận được "response" và server lại ko bị stop.
Dường như Thống đã chém gió hơi lố đà rầu các bác ạ. Server phải stop sau khi panicking đúng ko nào ?
image.png

What's wrong in here ? 😁😁Lol thật ra thì cái server của Thống đã có sẵn cơ chế recover từ GIN framework với câu lệnh gin.Default và "net/http" library rồi(recovery of gin and recover of http).
Chúng ta không cần handle panic nữa và hẹn gặp lại các bạn lần sau (ah mình lại đùa đấy 😅😅). Để ko mất thời gian, ta sẽ back lai cái client response ở trên. Về cơ bản, thằng GIN nó chỉ support chúng ta cái mã lỗi 5 xị thôi và một good server thì không thễ nào trả về mỗi cái mã lỗi như vậy được. Chúng ta phải giành lại cái quyền trả về lỗi đó.
Vậy công việc bây giờ là bằng cách nào đó, phải catch "error" và format error và trả về client trước 2 thằng "recover" ở trên nó đụng tới.

Add middleware for recover a panic


image.png
image.png
Tác giả của GIN dường như cũng đã thấy ra vấn đề này và set up cho chúng ta sẵn cơ chế middleware. Chúng ta chỉ việc recover a panic tại middleware và include nó vào server qua hàm "router.Use()". Tất nhiên, GIN sẽ set up request cho gặp middleware trước khi gặp 2 thằng recover kia.

Call server again with recover middleware:
image.png

Vài lời sau cuối

  • Rất cám ơn bạn đã chịu khó khi vẫn còn ngồi ở đây 😁😁.
  • Về ví dụ và định nghĩa, defer, recover, panic có rất nhiều trên mạng (i.e https://go.dev/play/p/g0ZfIRqKnrn). Nhưng để đọc xong nó và áp dụng vào thực tế thì không hề đơn giản. Như ví dụ ở trên mình làm với GIN, nhưng nếu swap qua mux.Router thì chúng ta cũng phải xem xét làm sao để có thể xư lí request trước khi cơ chế recover của nó đụng tới.
  • Về format error, tùy theo dự án mà bạn có thể set up theo cách bạn muốn. Mình chỉ để tạm thời để ví dụ đơn giản ở đây thôi nhé.
  • Nếu thấy hay tặng Thống 1 like nhé
  • Tham khảo:

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í