ืืคื ื ืืืฉ ืฉื ืื ืืชืืืชื
ืืืืจ ืื ืขืืกืง ืืืชืืืช ืฉืจืช ื-Go. ื ืชืืื ืืืืจืื ืคืฉืืืื ืืื "ืฉืืื ืขืืื!" ืื ืกืืื ืืืคืืืงืฆืื ืขื ืืืืืืืช ืืืืืช:
- ืฉืืืืฉ ื-Let's Encrypt ืขืืืจ HTTPS.
- ืขืืืื ืื ืชื API.
- ืขืืืื ืขื ืชืืื ืช ืืื ืืื.
- ืขืืืื ืงืืฆืื ืกืืืืื.
- ืืืืื ื ืืื.
Skillbox ืืืืืฆื: ืงืืจืก ืืขืฉื
"ืืคืชื Python ืืืคืก" .ืื ื ืืืืืจืื: ืืื ืงืืจืื Habr - ืื ืื ืฉื 10 ืจืืื ืืขืช ืืจืฉืื ืืื ืงืืจืก Skillbox ืืืืฆืขืืช ืงืื ืืืืื ืฉื Habr.
ืฉืืื, ืขืืื!
ืืชื ืืืื ืืืฆืืจ ืฉืจืช ืืื ืืจื ื ื-Go ืืืืืจืืช ืจืื. ืื ื ืืืืื ืืฉืืืืฉ ืืืืคื ืฉืืืืืจ ืืช ื"ืฉืืื, ืขืืื!" ืฉืืืืื ืืขืื.
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)
}
ืืืืจ ืืื, ืื ืืชื ืืคืขืื ืืช ืืืืฉืื ืืคืืชื ืืช ืืืฃ
ื ืฉืชืืฉ ืืืืคื ืืกืคืจ ืคืขืืื ืืืืืจ ืืืชืจ, ืืื ืงืืื ืื ืืืื ื ืืื ืืื ืืื ืขืืื.
net/http
ืืืืืื ืืฉืชืืฉื ืืืืืื net/http
ืืืคืื HTTP
ืืืฉืจ ืื ื ืืงืืืื ืืงืฉื, ืืืืคื ืื ืชื ืืืชื ืืืืฆืจ ืชืืืื. ืืืคืืื ื-Go ืืืืฉืืื ืืืืคื ืืื:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
ืืืืืื ืืจืืฉืื ื ืืฉืชืืฉืช ืืคืื ืงืฆืืืช ืืขืืจ http.HandleFunc. ืื ืขืืืฃ ืคืื ืงืฆืื ื ืืกืคืช, ืฉืืชืืจื ืืืงืืช ืืช http.ResponseWriter ื- http.Request ืืชืื ServeHTTP.
ืืืืืื ืืืจืืช, ืืืคืืื ืืืืื ื ืืืฆืืื ืืืืฉืง ืืื, ืื ืฉื ืืชื ืืจืื ืืคืฉืจืืืืช ืืืชืื ืช. ืื, ืืืฉื, ืชืืื ืช ืืืื ืืื ืืืืฉืืช ืืืืฆืขืืช ืืืคื, ืืืฉืจ ServeHTTP ืชืืืื ืขืืฉื ืืฉืื ืืื ืงืืจื ืืฉืืืช ServeHTTP ืฉื ืืืคื ืืืจ.
ืืคื ืฉืืืืืจ ืืขืื, ืืืืคืืื ืคืฉืื ืืืฆืจืื ืชืืืืืช ืืืงืฉืืช. ืืื ืืืืื ืืืคื ืืกืืื ืืฉ ืืืฉืชืืฉ ืื ืงืืืช ืืื ืืกืืืืช?
ืืงืฉ ื ืืชืื
ืืื ืืขืฉืืช ืืช ืืืืืจื ืื ืืื ื, ืืฉืชืืฉ ืืืจืื HTTP. ืืืกืคืจ ืกืคืจืืืช ืื ื ืงืจื muxer ืื ื ืชื, ืืื ืืืื ืืืชื ืืืจ. ืชืคืงืืื ืฉื ืืืจืื ืืื ืื ืชื ืืช ื ืชืื ืืืงืฉื ืืืืืืจ ืืช ืืืืคื ืืืชืืื.
ืื ืืชื ืืงืืง ืืชืืืื ืื ืืชืื ืืืจืื, ืขืืืฃ ืืืฉืชืืฉ ืืกืคืจืืืช ืฉื ืฆื ืฉืืืฉื. ืืื ืืืืชืงืืืื ืืืืชืจ -
ืขืืืื ืขื ืืกืืจืืช ืืืจืืืืช ืืืฆื ืจืืื ืชืืจืืฉ ืคืชืจืื ืืช ืื ืกืื ืืจืืืื, ืืืืืจ ืืกืื ืืฉืืขืืชืืช ืืช ืืฉืืืืฉ ืืืืคืื ืืจืืจืช ืืืื. ืืื ืืืฆืืจ ืืช ืืจืื ืืืืจืืข ืฉื ืืืืฉืืืื, ืฉืืืื ืฉื ืกืคืจืืืช ืืจืืจืช ืืืืื ืื ืชื ืคืฉืื ืืกืคืืง.
ืขืืืื ืฉืืืืชืืช
ืื ืืกืฃ, ืื ืื ื ืฆืจืืืื ืจืืื ืฉ"ืืงืฉืื" ืืืืืืจืื ื ืื ืกืื ืืืคื ื ืืช ืื ืืืงืฉืืช ืืืืคื ืื ืืื. http.Server ืืืื ืืืชืืืื ืืงืืืช ืขื ืืฉืืื ืื.
ืืืื ืขืืื ืื ืืฉืจืช ืืืจืื ืืื ืืืฉืืืืช ืืงืฉืืจืืช ืืขืืืื ืืืืืจืื. ืื, ืืืฉื, ืขืืื ืืืืฆืขืืช ืคืจืืืืงืื TLS. ืืื ืืืืฉื ืืช ืืงืจืืื http.ListenAndServer, ื ืขืฉื ืฉืืืืฉ ืืฉืจืช HTTP ืกืื ืืจืื.
ืขืืฉืื ืืืื ื ืกืชืื ืขื ืืืืืืืช ืืืจืืืืช ืืืชืจ.
ืืืกืคืช Let's Encrypt
ืืืจืืจืช ืืืื, ืืืคืืืงืฆืื ืฉืื ื ืคืืขืืช ืขื ืคืจืืืืงืื HTTP, ืื ืืืืืฅ ืืืฉืชืืฉ ืืคืจืืืืงืื HTTPS. ื ืืชื ืืขืฉืืช ืืืช ืืื ืืขืืืช ื-Go. ืื ืงืืืืชื ืชืขืืื ืืืคืชื ืคืจืื, ืืกืคืืง ืืจืฉืื ืืช ListenAndServeTLS ืขื ืงืืฆื ืืชืขืืื ืืืืคืชื ืื ืืื ืื.
http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)
ืืชื ืชืืื ืืืื ืืขืฉืืช ืืืชืจ ืืื.
autocert
.
ืืืจื ืืงืื ืืืืชืจ ืืืืืืจ ืืืชื ืืื ืืืฉืชืืฉ ืืฉืืืช autocert.NewListener ืืฉืืืื ืขื http.Serve. ืืฉืืื ืืืคืฉืจืช ืื ืืืฉืื ืืืขืืื ืืืฉืืจื TLS ืืืื ืฉืฉืจืช ื-HTTP ืืขืื ืืงืฉืืช:
http.Serve(autocert.NewListener("example.com"), nil)
ืื ื ืคืชื ืืืคืืคื
ืื ืืชื ืฆืจืื ืชืฆืืจื ืืคืืจืืช ืืืชืจ, ืขืืื ืืืฉืชืืฉ ืืื ืื autocert.Manager. ืืืืจ ืืื ืื ื ืืืฆืจืื ืืืคืข http.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("", "")
ืืืื ืืจื ืงืื ืืืืฉื ืชืืืื ืืืื ื-HTTPS ืขื ืืืืืฉ ืืืฉืืจ ืืืืืืื.
ืืืกืคืช ืืกืืืืื ืืืชืืืื ืืืฉืืช
ื ืชื ืืจืืจืช ืืืืื ืืืืื ืืกืคืจืืื ืืกืื ืืจืืืช ืืื ืืื, ืืื ืืื ืืกืืกื ืืืื. ืจืื ืืืืฉืืืื ืืืจืฉืื ื ืืชืื ืืืจืื ืืืชืจ, ืืืื ืืกืืืืื ืืงืื ื ืื ืืชืืืื ืืืืืื, ืื ืืืื ืืืืืจืช ืืคืืกื ื ืชืื ืืคืจืืืจืื.
ืืืงืจื ืื ืืืื ืืืฉืชืืฉ ืืืืืืืช
ื ืชืื ืืงืืืฅ api/v1/api.go ืืืืื ืืกืืืืื ืขืืืจ ื-API ืฉืื ื:
/ HelloResponse is the JSON representation for a customized message
type HelloResponse struct {
Message string `json:"message"`
}
// HelloName returns a personalized JSON message
func HelloName(w http.ResponseWriter, r *http.Request) {
name := chi.URLParam(r, "name")
response := HelloResponse{
Message: fmt.Sprintf("Hello %s!", name),
}
jsonResponse(w, response, http.StatusOK)
}
// NewRouter returns an HTTP handler that implements the routes for the API
func NewRouter() http.Handler {
r := chi.NewRouter()
r.Get("/{name}", HelloName)
return r
}
ืื ืื ื ืืืืืจืื ืืช ืงืืืืืช api/vq ืืืกืืืืื ืืงืืืฅ ืืจืืฉื.
ืืืืจ ืืื ื ืืื ืืืจืืื ืืช ืื ืื ืชื ืืจืืฉื ืฉืื ื ืชืืช ืืงืืืืืช api/v1/ ืืืืจื ืืืคืืืงืฆืื ืืจืืฉืืช ืฉืื ื:
// NewRouter returns a new HTTP handler that implements the main server routes
func NewRouter() http.Handler {
router := chi.NewRouter()
router.Mount("/api/v1/", v1.NewRouter())
return router
}
http.Serve(autocert.NewListener("example.com"), NewRouter())
ืงืืืช ืืขืืืื ืฉื Go ืขื ืืกืืืืื ืืืจืืืื ืืืคืฉืจืช ืืคืฉื ืืช ืืืื ื ืืืชืืืืงื ืฉื ืืคืืืงืฆืืืช ืืืืืืช ืืืืจืืืืช.
ืขืืืื ืขื ืชืืื ืช ืืื ืืื
ืืืืื ืืจืื ืืขืืืฃ ืืืคื HTTP ืืื ืืืืจ, ืื ืฉืืืคืฉืจ ืืืฆืข ืืืืืจืืช ืืืืืช, ืืืืกื, ืจืืฉืื ืืืกืคืจ ืคืื ืงืฆืืืช ืืืจืืช.
ืืืืืื, ืืื ื ืกืชืื ืขื ืืืฉืง http.Handler; ื ืฉืชืืฉ ืื ืืื ืืืชืื ืืืคื ืฉืืืืช ืืฉืชืืฉื ืฉืืจืืช.
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
}
// Assuming authentication passed, run the original handler
next.ServeHTTP(w, r)
})
}
ืืฉื ื ื ืชืืื ืฉื ืฆื ืฉืืืฉื, ืืืื chi, ืืืืคืฉืจืื ืื ืืืจืืื ืืช ืคืื ืงืฆืืื ืืืืช ืืชืืื.
ืขืืืื ืขื ืงืืฆืื ืกืืืืื
ืกืคืจืืืช ืืชืงื Go ืืืืืช ืืืืืืช ืืขืืืื ืขื ืชืืื ืกืืื, ืืืื ืชืืื ืืช, ืงืืืฆื JavaScript ื-CSS. ื ืืชื ืืืฉืช ืืืืื ืืจื ืืคืื ืงืฆืื http.FileServer. ืื ืืืืืจ ืืืคื ืฉืืืืฉ ืงืืฆืื ืืกืคืจืืื ืกืคืฆืืคืืช.
func NewRouter() http.Handler {
router := chi.NewRouter()
r.Get("/{name}", HelloName)
// ะะฐัััะพะนะบะฐ ัะฐะทะดะฐัะธ ััะฐัะธัะตัะบะธั
ัะฐะนะปะพะฒ
staticPath, _ := filepath.Abs("../../static/")
fs := http.FileServer(http.Dir(staticPath))
router.Handle("/*", fs)
return r
ืืืื ืืืืื ืืืืืจ ืฉ-http.Dir ืืฆืื ืืช ืชืืื ืืกืคืจืืื ืื ืืื ืื ืืืืื ืืช ืืงืืืฅ ืืจืืฉื index.html. ืืืงืจื ืื, ืืื ืืื ืืข ืืืกืคืจืืื ืืืืคืืข, ืขืืื ืืืฉืชืืฉ ืืืืืื unindexed
ืืืืื ื ืืื
ื- Go ืืฉ ืื ืชืืื ื ืื ืงืจืืช ืืืืื ืืื ื ื ืฉื ืฉืจืช ื-HTTP. ื ืืชื ืืขืฉืืช ืืืช ืืืืฆืขืืช ืฉืืืช Shutdown() . ืืฉืจืช ืืืคืขื ื-goroutine, ืืืืืจ ืืื ืืืืื ืื ืืขืจืืฅ ืืื ืืงืื ืืืช ืคืกืืงื. ืืจืืข ืฉืืืืช ืืชืงืื, ืืฉืจืช ื ืืื, ืื ืื ืืื, ืืื ืืืืจ ืืกืคืจ ืฉื ืืืช.
handler := server.NewRouter()
srv := &http.Server{
Handler: handler,
}
go func() {
srv.Serve(autocert.NewListener(domains...))
}()
// Wait for an interrupt
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
// Attempt a graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
srv.Shutdown(ctx)
ืืืกืงื ื
Go ืืื ืฉืคื ืจืืช ืขืืฆืื ืขื ืกืคืจืืื ืกืื ืืจืืืช ืืืขื ืืื ืืืจืกืืืช. ืืืืืืช ืืจืืจืช ืืืืื ืฉืื ืจืืืืช ืืืื, ืื ืืชื ืืฉืคืจ ืืืชื ืืืืฆืขืืช ืืืฉืงืื - ืื ืืืคืฉืจ ืืคืชื ืฉืจืชื HTTP ืืืื ืื ืืืืช.
Skillbox ืืืืืฆื:
- ืงืืจืก ืืขืฉื ืฉื ืชืืื
"ืื ื ืืคืชื ืืชืจืื PRO" .- ืงืืจืก ืืื ืืื ืืงืืื
"ืืงืฆืืขื ืืคืชื ื'ืืืื" .- ืงืืจืก ืืขืฉื ืื ืฉื ื
"ืืคืชื PHP ื-0 ื-PRO" .
ืืงืืจ: www.habr.com