Remove Gin from simple endpoints for TS2019

This commit is contained in:
Juan Font Alonso 2022-06-17 16:48:04 +02:00
parent 3ae340527f
commit 367da0fcc2
4 changed files with 111 additions and 96 deletions

36
api.go
View file

@ -32,12 +32,13 @@ const (
// KeyHandler provides the Headscale pub key // KeyHandler provides the Headscale pub key
// Listens in /key. // Listens in /key.
func (h *Headscale) KeyHandler(ctx *gin.Context) { func (h *Headscale) KeyHandler(
ctx.Data( w http.ResponseWriter,
http.StatusOK, r *http.Request,
"text/plain; charset=utf-8", ) {
[]byte(MachinePublicKeyStripPrefix(h.privateKey.Public())), w.Header().Set("Content-Type", "text/plain; charset=utf-8")
) w.WriteHeader(http.StatusOK)
w.Write([]byte(MachinePublicKeyStripPrefix(h.privateKey.Public())))
} }
type registerWebAPITemplateConfig struct { type registerWebAPITemplateConfig struct {
@ -63,10 +64,15 @@ var registerWebAPITemplate = template.Must(
// RegisterWebAPI shows a simple message in the browser to point to the CLI // RegisterWebAPI shows a simple message in the browser to point to the CLI
// Listens in /register. // Listens in /register.
func (h *Headscale) RegisterWebAPI(ctx *gin.Context) { func (h *Headscale) RegisterWebAPI(
machineKeyStr := ctx.Query("key") w http.ResponseWriter,
r *http.Request,
) {
machineKeyStr := r.URL.Query().Get("key")
if machineKeyStr == "" { 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 return
} }
@ -79,14 +85,14 @@ func (h *Headscale) RegisterWebAPI(ctx *gin.Context) {
Str("func", "RegisterWebAPI"). Str("func", "RegisterWebAPI").
Err(err). Err(err).
Msg("Could not render register web API template") Msg("Could not render register web API template")
ctx.Data( w.Header().Set("Content-Type", "text/plain; charset=utf-8")
http.StatusInternalServerError, w.WriteHeader(http.StatusInternalServerError)
"text/html; charset=utf-8", w.Write([]byte("Could not render register web API template"))
[]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 // RegistrationHandler handles the actual registration process of a machine

16
app.go
View file

@ -397,18 +397,18 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine {
"/health", "/health",
func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"healthy": "ok"}) }, func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"healthy": "ok"}) },
) )
router.GET("/key", h.KeyHandler) router.GET("/key", gin.WrapF(h.KeyHandler))
router.GET("/register", h.RegisterWebAPI) router.GET("/register", gin.WrapF(h.RegisterWebAPI))
router.POST("/machine/:id/map", h.PollNetMapHandler) router.POST("/machine/:id/map", h.PollNetMapHandler)
router.POST("/machine/:id", h.RegistrationHandler) router.POST("/machine/:id", h.RegistrationHandler)
router.GET("/oidc/register/:mkey", h.RegisterOIDC) router.GET("/oidc/register/:mkey", h.RegisterOIDC)
router.GET("/oidc/callback", h.OIDCCallback) router.GET("/oidc/callback", h.OIDCCallback)
router.GET("/apple", h.AppleConfigMessage) router.GET("/apple", gin.WrapF(h.AppleConfigMessage))
router.GET("/apple/:platform", h.ApplePlatformConfig) router.GET("/apple/:platform", gin.WrapF(h.ApplePlatformConfig))
router.GET("/windows", h.WindowsConfigMessage) router.GET("/windows", gin.WrapF(h.WindowsConfigMessage))
router.GET("/windows/tailscale.reg", h.WindowsRegConfig) router.GET("/windows/tailscale.reg", gin.WrapF(h.WindowsRegConfig))
router.GET("/swagger", SwaggerUI) router.GET("/swagger", gin.WrapF(SwaggerUI))
router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1) router.GET("/swagger/v1/openapiv2.json", gin.WrapF(SwaggerAPIv1))
if h.cfg.DERP.ServerEnabled { if h.cfg.DERP.ServerEnabled {
router.Any("/derp", h.DERPHandler) router.Any("/derp", h.DERPHandler)

View file

@ -6,13 +6,15 @@ import (
"net/http" "net/http"
textTemplate "text/template" textTemplate "text/template"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
// WindowsConfigMessage shows a simple message in the browser for how to configure the Windows Tailscale client. // 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(` winTemplate := template.Must(template.New("windows").Parse(`
<html> <html>
<body> <body>
@ -63,20 +65,24 @@ REG ADD "HKLM\Software\Tailscale IPN" /v LoginURL /t REG_SZ /d "{{.URL}}"</code>
Str("handler", "WindowsRegConfig"). Str("handler", "WindowsRegConfig").
Err(err). Err(err).
Msg("Could not render Windows index template") Msg("Could not render Windows index template")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Could not render Windows index template"), w.Write([]byte("Could not render Windows index template"))
)
return 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. // 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{ config := WindowsRegistryConfig{
URL: h.cfg.ServerURL, URL: h.cfg.ServerURL,
} }
@ -87,24 +93,24 @@ func (h *Headscale) WindowsRegConfig(ctx *gin.Context) {
Str("handler", "WindowsRegConfig"). Str("handler", "WindowsRegConfig").
Err(err). Err(err).
Msg("Could not render Apple macOS template") Msg("Could not render Apple macOS template")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Could not render Windows registry template"), w.Write([]byte("Could not render Windows registry template"))
)
return return
} }
ctx.Data( w.Header().Set("Content-Type", "text/x-ms-regedit; charset=utf-8")
http.StatusOK, w.WriteHeader(http.StatusOK)
"text/x-ms-regedit; charset=utf-8", w.Write(content.Bytes())
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. // 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(` appleTemplate := template.Must(template.New("apple").Parse(`
<html> <html>
<body> <body>
@ -165,20 +171,24 @@ func (h *Headscale) AppleConfigMessage(ctx *gin.Context) {
Str("handler", "AppleMobileConfig"). Str("handler", "AppleMobileConfig").
Err(err). Err(err).
Msg("Could not render Apple index template") Msg("Could not render Apple index template")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Could not render Apple index template"), w.Write([]byte("Could not render Apple index template"))
)
return 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) { func (h *Headscale) ApplePlatformConfig(
platform := ctx.Param("platform") w http.ResponseWriter,
r *http.Request,
) {
platform := r.URL.Query().Get("platform")
id, err := uuid.NewV4() id, err := uuid.NewV4()
if err != nil { if err != nil {
@ -186,11 +196,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) {
Str("handler", "ApplePlatformConfig"). Str("handler", "ApplePlatformConfig").
Err(err). Err(err).
Msg("Failed not create UUID") Msg("Failed not create UUID")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Failed to create UUID"), w.Write([]byte("Failed to create UUID"))
)
return return
} }
@ -201,11 +210,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) {
Str("handler", "ApplePlatformConfig"). Str("handler", "ApplePlatformConfig").
Err(err). Err(err).
Msg("Failed not create UUID") Msg("Failed not create UUID")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Failed to create UUID"), w.Write([]byte("Failed to create content UUID"))
)
return return
} }
@ -224,11 +232,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) {
Str("handler", "ApplePlatformConfig"). Str("handler", "ApplePlatformConfig").
Err(err). Err(err).
Msg("Could not render Apple macOS template") Msg("Could not render Apple macOS template")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Could not render Apple macOS template"), w.Write([]byte("Could not render Apple macOS template"))
)
return return
} }
@ -238,20 +245,17 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) {
Str("handler", "ApplePlatformConfig"). Str("handler", "ApplePlatformConfig").
Err(err). Err(err).
Msg("Could not render Apple iOS template") Msg("Could not render Apple iOS template")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Could not render Apple iOS template"), w.Write([]byte("Could not render Apple iOS template"))
)
return return
} }
default: default:
ctx.Data( w.Header().Set("Content-Type", "text/plain; charset=utf-8")
http.StatusOK, w.WriteHeader(http.StatusBadRequest)
"text/html; charset=utf-8", w.Write([]byte("Invalid platform, only ios and macos is supported"))
[]byte("Invalid platform, only ios and macos is supported"),
)
return return
} }
@ -268,20 +272,17 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) {
Str("handler", "ApplePlatformConfig"). Str("handler", "ApplePlatformConfig").
Err(err). Err(err).
Msg("Could not render Apple platform template") Msg("Could not render Apple platform template")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Could not render Apple platform template"), w.Write([]byte("Could not render Apple platform template"))
)
return return
} }
ctx.Data( w.Header().Set("Content-Type", "application/x-apple-aspen-config; charset=utf-8")
http.StatusOK, w.WriteHeader(http.StatusOK)
"application/x-apple-aspen-config; charset=utf-8", w.Write(content.Bytes())
content.Bytes(),
)
} }
type WindowsRegistryConfig struct { type WindowsRegistryConfig struct {

View file

@ -6,14 +6,16 @@ import (
"html/template" "html/template"
"net/http" "net/http"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
//go:embed gen/openapiv2/headscale/v1/headscale.swagger.json //go:embed gen/openapiv2/headscale/v1/headscale.swagger.json
var apiV1JSON []byte var apiV1JSON []byte
func SwaggerUI(ctx *gin.Context) { func SwaggerUI(
w http.ResponseWriter,
r *http.Request,
) {
swaggerTemplate := template.Must(template.New("swagger").Parse(` swaggerTemplate := template.Must(template.New("swagger").Parse(`
<html> <html>
<head> <head>
@ -52,18 +54,24 @@ func SwaggerUI(ctx *gin.Context) {
Caller(). Caller().
Err(err). Err(err).
Msg("Could not render Swagger") Msg("Could not render Swagger")
ctx.Data(
http.StatusInternalServerError, w.Header().Set("Content-Type", "text/plain; charset=utf-8")
"text/html; charset=utf-8", w.WriteHeader(http.StatusInternalServerError)
[]byte("Could not render Swagger"), w.Write([]byte("Could not render Swagger"))
)
return 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) { func SwaggerAPIv1(
ctx.Data(http.StatusOK, "application/json; charset=utf-8", apiV1JSON) w http.ResponseWriter,
r *http.Request,
) {
w.Header().Set("Content-Type", "application/json; charset=utf-88")
w.WriteHeader(http.StatusOK)
w.Write(apiV1JSON)
} }