diff --git a/api.go b/api.go index 45fd7793..3d4c2b7c 100644 --- a/api.go +++ b/api.go @@ -32,12 +32,13 @@ const ( // KeyHandler provides the Headscale pub key // Listens in /key. -func (h *Headscale) KeyHandler(ctx *gin.Context) { - ctx.Data( - http.StatusOK, - "text/plain; charset=utf-8", - []byte(MachinePublicKeyStripPrefix(h.privateKey.Public())), - ) +func (h *Headscale) KeyHandler( + w http.ResponseWriter, + r *http.Request, +) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusOK) + w.Write([]byte(MachinePublicKeyStripPrefix(h.privateKey.Public()))) } type registerWebAPITemplateConfig struct { @@ -63,10 +64,15 @@ var registerWebAPITemplate = template.Must( // RegisterWebAPI shows a simple message in the browser to point to the CLI // Listens in /register. -func (h *Headscale) RegisterWebAPI(ctx *gin.Context) { - machineKeyStr := ctx.Query("key") +func (h *Headscale) RegisterWebAPI( + w http.ResponseWriter, + r *http.Request, +) { + machineKeyStr := r.URL.Query().Get("key") if machineKeyStr == "" { - ctx.String(http.StatusBadRequest, "Wrong params") + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte("Wrong params")) return } @@ -79,14 +85,14 @@ func (h *Headscale) RegisterWebAPI(ctx *gin.Context) { Str("func", "RegisterWebAPI"). Err(err). Msg("Could not render register web API template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render register web API template"), - ) + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render register web API template")) } - ctx.Data(http.StatusOK, "text/html; charset=utf-8", content.Bytes()) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusOK) + w.Write(content.Bytes()) } // RegistrationHandler handles the actual registration process of a machine diff --git a/app.go b/app.go index 917d32b8..3d24d81c 100644 --- a/app.go +++ b/app.go @@ -397,18 +397,18 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { "/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"healthy": "ok"}) }, ) - router.GET("/key", h.KeyHandler) - router.GET("/register", h.RegisterWebAPI) + router.GET("/key", gin.WrapF(h.KeyHandler)) + router.GET("/register", gin.WrapF(h.RegisterWebAPI)) router.POST("/machine/:id/map", h.PollNetMapHandler) router.POST("/machine/:id", h.RegistrationHandler) router.GET("/oidc/register/:mkey", h.RegisterOIDC) router.GET("/oidc/callback", h.OIDCCallback) - router.GET("/apple", h.AppleConfigMessage) - router.GET("/apple/:platform", h.ApplePlatformConfig) - router.GET("/windows", h.WindowsConfigMessage) - router.GET("/windows/tailscale.reg", h.WindowsRegConfig) - router.GET("/swagger", SwaggerUI) - router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1) + router.GET("/apple", gin.WrapF(h.AppleConfigMessage)) + router.GET("/apple/:platform", gin.WrapF(h.ApplePlatformConfig)) + router.GET("/windows", gin.WrapF(h.WindowsConfigMessage)) + router.GET("/windows/tailscale.reg", gin.WrapF(h.WindowsRegConfig)) + router.GET("/swagger", gin.WrapF(SwaggerUI)) + router.GET("/swagger/v1/openapiv2.json", gin.WrapF(SwaggerAPIv1)) if h.cfg.DERP.ServerEnabled { router.Any("/derp", h.DERPHandler) diff --git a/platform_config.go b/platform_config.go index d36a37ce..8407feaa 100644 --- a/platform_config.go +++ b/platform_config.go @@ -6,13 +6,15 @@ import ( "net/http" textTemplate "text/template" - "github.com/gin-gonic/gin" "github.com/gofrs/uuid" "github.com/rs/zerolog/log" ) // WindowsConfigMessage shows a simple message in the browser for how to configure the Windows Tailscale client. -func (h *Headscale) WindowsConfigMessage(ctx *gin.Context) { +func (h *Headscale) WindowsConfigMessage( + w http.ResponseWriter, + r *http.Request, +) { winTemplate := template.Must(template.New("windows").Parse(` @@ -63,20 +65,24 @@ REG ADD "HKLM\Software\Tailscale IPN" /v LoginURL /t REG_SZ /d "{{.URL}}" Str("handler", "WindowsRegConfig"). Err(err). Msg("Could not render Windows index template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render Windows index template"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render Windows index template")) return } - ctx.Data(http.StatusOK, "text/html; charset=utf-8", payload.Bytes()) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusOK) + w.Write(payload.Bytes()) } // WindowsRegConfig generates and serves a .reg file configured with the Headscale server address. -func (h *Headscale) WindowsRegConfig(ctx *gin.Context) { +func (h *Headscale) WindowsRegConfig( + w http.ResponseWriter, + r *http.Request, +) { config := WindowsRegistryConfig{ URL: h.cfg.ServerURL, } @@ -87,24 +93,24 @@ func (h *Headscale) WindowsRegConfig(ctx *gin.Context) { Str("handler", "WindowsRegConfig"). Err(err). Msg("Could not render Apple macOS template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render Windows registry template"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render Windows registry template")) return } - ctx.Data( - http.StatusOK, - "text/x-ms-regedit; charset=utf-8", - content.Bytes(), - ) + w.Header().Set("Content-Type", "text/x-ms-regedit; charset=utf-8") + w.WriteHeader(http.StatusOK) + w.Write(content.Bytes()) } // AppleConfigMessage shows a simple message in the browser to point the user to the iOS/MacOS profile and instructions for how to install it. -func (h *Headscale) AppleConfigMessage(ctx *gin.Context) { +func (h *Headscale) AppleConfigMessage( + w http.ResponseWriter, + r *http.Request, +) { appleTemplate := template.Must(template.New("apple").Parse(` @@ -165,20 +171,24 @@ func (h *Headscale) AppleConfigMessage(ctx *gin.Context) { Str("handler", "AppleMobileConfig"). Err(err). Msg("Could not render Apple index template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render Apple index template"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render Apple index template")) return } - ctx.Data(http.StatusOK, "text/html; charset=utf-8", payload.Bytes()) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusOK) + w.Write(payload.Bytes()) } -func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) { - platform := ctx.Param("platform") +func (h *Headscale) ApplePlatformConfig( + w http.ResponseWriter, + r *http.Request, +) { + platform := r.URL.Query().Get("platform") id, err := uuid.NewV4() if err != nil { @@ -186,11 +196,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) { Str("handler", "ApplePlatformConfig"). Err(err). Msg("Failed not create UUID") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Failed to create UUID"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Failed to create UUID")) return } @@ -201,11 +210,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) { Str("handler", "ApplePlatformConfig"). Err(err). Msg("Failed not create UUID") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Failed to create UUID"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Failed to create content UUID")) return } @@ -224,11 +232,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) { Str("handler", "ApplePlatformConfig"). Err(err). Msg("Could not render Apple macOS template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render Apple macOS template"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render Apple macOS template")) return } @@ -238,20 +245,17 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) { Str("handler", "ApplePlatformConfig"). Err(err). Msg("Could not render Apple iOS template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render Apple iOS template"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render Apple iOS template")) return } default: - ctx.Data( - http.StatusOK, - "text/html; charset=utf-8", - []byte("Invalid platform, only ios and macos is supported"), - ) + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Invalid platform, only ios and macos is supported")) return } @@ -268,20 +272,17 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) { Str("handler", "ApplePlatformConfig"). Err(err). Msg("Could not render Apple platform template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render Apple platform template"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render Apple platform template")) return } - ctx.Data( - http.StatusOK, - "application/x-apple-aspen-config; charset=utf-8", - content.Bytes(), - ) + w.Header().Set("Content-Type", "application/x-apple-aspen-config; charset=utf-8") + w.WriteHeader(http.StatusOK) + w.Write(content.Bytes()) } type WindowsRegistryConfig struct { diff --git a/swagger.go b/swagger.go index bad348db..473c834f 100644 --- a/swagger.go +++ b/swagger.go @@ -6,14 +6,16 @@ import ( "html/template" "net/http" - "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" ) //go:embed gen/openapiv2/headscale/v1/headscale.swagger.json var apiV1JSON []byte -func SwaggerUI(ctx *gin.Context) { +func SwaggerUI( + w http.ResponseWriter, + r *http.Request, +) { swaggerTemplate := template.Must(template.New("swagger").Parse(` @@ -52,18 +54,24 @@ func SwaggerUI(ctx *gin.Context) { Caller(). Err(err). Msg("Could not render Swagger") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render Swagger"), - ) + + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Could not render Swagger")) return } - ctx.Data(http.StatusOK, "text/html; charset=utf-8", payload.Bytes()) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusOK) + w.Write(payload.Bytes()) } -func SwaggerAPIv1(ctx *gin.Context) { - ctx.Data(http.StatusOK, "application/json; charset=utf-8", apiV1JSON) +func SwaggerAPIv1( + w http.ResponseWriter, + r *http.Request, +) { + w.Header().Set("Content-Type", "application/json; charset=utf-88") + w.WriteHeader(http.StatusOK) + w.Write(apiV1JSON) }