Herkese merhaba!

Uzun yıllardır bol miktarda kişisel zaman ve enerji harcayarak bilgimizi hepinizle paylaşıyoruz. Ancak şu andan itibaren bu blogu çalışır durumda tutabilmek için yardımınıza ihtiyacımız var. Yapmanız gereken tek şey, sitedeki reklamlardan birine tıklamak olacaktır, aksi takdirde hosting vb. masraflar nedeniyle maalesef yayından kaldırılacaktır. Teşekkürler.

Eğer HTTP API uygulamanızda belirli bazı satırları tekrarlamadan 500 Internal Server Error yanıtını istemciye göndermek isterseniz, aşağıdaki örneği kullanabilirsiniz. Burada bir tane sunucu seviyesinde 'middleware' kullanıyoruz, yani sizin yapmanız gereken tek şey middleware.InternalServerResponse() fonksiyonunu kullanmak olacaktır.


Yapı


.
├── cmd
│   └── client
│   └── main.go
├── go.mod
└── internal
├── pkg
│   └── middleware
│   ├── internalservererror.go
│   └── middleware.go
└── user
└── create.go

Dosyalar


main.go


package main

import (
"log"
"net/http"

"internal/pkg/middleware"
"internal/user"
)

func main() {
http.HandleFunc("/users", user.Create{}.Handle)

log.Fatal(http.ListenAndServe(":8888", middleware.Server(nil, middleware.InternalServerError)))
}

middleware.go


package middleware

import "net/http"

// server represents a server level middleware and is used for chaining.
type server func(http.Handler) http.Handler

// Server is used for middleware chaining and dedicated to HTTP server.
func Server(handler http.Handler, middleware ...server) http.Handler {
for _, m := range middleware {
handler = m(handler)
}

return handler
}

internalservererror.go


package middleware

import "net/http"

// InternalServerError catches all `panic` calls in order to prevent HTTP server
// from going down and return a standardised 500 Internal Server Error response.
func InternalServerError(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("Standard error message."))
}
}()

handler.ServeHTTP(w, r)
})
}

// TriggerInternalServerError is called from anywhere in the application in order
// to trigger 500 Internal Server Error response.
func TriggerInternalServerError() {
panic("")
}

create.go


Sizin de tahmin ettiğiniz gibi, middleware.TriggerInternalServerError() fonksiyonunu bilerek çağırıyorum.


package user

import (
"log"
"net/http"

"internal/pkg/middleware"
)

type Create struct {}

func (c Create) Handle(w http.ResponseWriter, r *http.Request) {
// This will cause 500 Internal Server error on purpose.
c.create()

// Since the function above terminates the whole process with an
// Internal Server error, this line onwards will never be executed.

w.WriteHeader(http.StatusCreated)
_, _ = w.Write([]byte("created"))
}

func (Create) create() {
// Some valid code.
// ...

// After this line, nothing after gets executed so no need for
// manual `return` or `exit`.
log.Println("Database is down.")
middleware.TriggerInternalServerError()

// Some valid code.
// ...
}

Test


$ curl -i http://localhost:8888/users
HTTP/1.1 500 Internal Server Error
Date: Thu, 13 Feb 2020 21:32:06 GMT
Content-Length: 23
Content-Type: text/plain; charset=utf-8

Standard error message