eintopf.info@v0.13.16/service/killswitch/transport.go (about) 1 // Copyright (C) 2022 The Eintopf authors 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 16 package killswitch 17 18 import ( 19 "net/http" 20 "strings" 21 22 "github.com/go-chi/chi/v5" 23 24 "eintopf.info/internal/xhttp" 25 ) 26 27 // Router returns a new killswitch router. 28 func Router(service Service) func(chi.Router) { 29 server := &server{service} 30 return func(r chi.Router) { 31 r.Options("/turnon", xhttp.CorsHandler) 32 33 // swagger:route GET /killswitch/turnon/{hash} killswitch kill 34 // 35 // Sets the internal state to on, provided a valid hash was provided. 36 // 37 // Responses: 38 // 200: loginSuccess 39 // 400: badRequest 40 // 500: internalError 41 r.Get("/turnon/{hash}", server.turnOn) 42 43 r.Options("/turnoff", xhttp.CorsHandler) 44 45 // swagger:route GET /killswitch/turnoff/{hash} killswitch resurrect 46 // 47 // Sets the internal state to off, provided the hash is valid 48 // When the state is off, the server will respond with a 503 status 49 // code. 50 // 51 // 52 // Responses: 53 // 200: loginSuccess 54 // 400: badRequest 55 // 500: internalError 56 // 503: serviceUnavailable 57 r.Get("/turnoff/{hash}", server.turnOff) 58 } 59 } 60 61 type server struct { 62 service Service 63 } 64 65 func (s *server) turnOn(w http.ResponseWriter, r *http.Request) { 66 hash := chi.URLParam(r, "hash") 67 err := s.service.TurnOn(r.Context(), hash) 68 if err != nil { 69 xhttp.WriteError(r.Context(), w, err) 70 return 71 } 72 w.Write([]byte{}) 73 } 74 75 func (s *server) turnOff(w http.ResponseWriter, r *http.Request) { 76 hash := chi.URLParam(r, "hash") 77 err := s.service.TurnOff(r.Context(), hash) 78 if err != nil { 79 xhttp.WriteError(r.Context(), w, err) 80 return 81 } 82 w.Write([]byte{}) 83 } 84 85 // Middleware returns a new killswitch middleware. 86 // It checks wether the state is on. If not it writes a 503 response. 87 func Middleware(service Service) func(next http.Handler) http.Handler { 88 return func(next http.Handler) http.Handler { 89 fn := func(w http.ResponseWriter, r *http.Request) { 90 on, err := service.On(r.Context()) 91 if err != nil { 92 xhttp.WriteInternalError(r.Context(), w, err) 93 } 94 if !on && !strings.Contains(r.RequestURI, "turnon") { 95 // Cancel the request when the state is off and the 96 // turnon endpoint wasn't called. 97 xhttp.WriteServiceUnavailable(w) 98 return 99 } 100 next.ServeHTTP(w, r) 101 } 102 return http.HandlerFunc(fn) 103 } 104 }