Skip to content

Commit 5586d16

Browse files
committed
Add endpoints to return nginx config from disk
1 parent ca4d92d commit 5586d16

File tree

5 files changed

+128
-0
lines changed

5 files changed

+128
-0
lines changed

backend/internal/api/handler/hosts.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,45 @@ func DeleteHost() func(http.ResponseWriter, *http.Request) {
164164
}
165165
}
166166

167+
// GetHostNginxConfig will return a Host's nginx config from disk
168+
// Route: GET /hosts/{hostID}/nginx-config
169+
// Route: GET /hosts/{hostID}/nginx-config.txt
170+
func GetHostNginxConfig(format string) func(http.ResponseWriter, *http.Request) {
171+
return func(w http.ResponseWriter, r *http.Request) {
172+
var err error
173+
var hostID int
174+
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
175+
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
176+
return
177+
}
178+
179+
item, err := host.GetByID(hostID)
180+
switch err {
181+
case sql.ErrNoRows:
182+
h.ResultErrorJSON(w, r, http.StatusNotFound, "Not found", nil)
183+
case nil:
184+
// Get the config from disk
185+
content, nErr := nginx.GetHostConfigContent(item)
186+
if nErr != nil {
187+
h.ResultErrorJSON(w, r, http.StatusBadRequest, nErr.Error(), nil)
188+
return
189+
}
190+
if format == "text" {
191+
h.ResultResponseText(w, r, http.StatusOK, content)
192+
return
193+
}
194+
195+
j := struct {
196+
Content string `json:"content"`
197+
}{Content: content}
198+
199+
h.ResultResponseJSON(w, r, http.StatusOK, j)
200+
default:
201+
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
202+
}
203+
}
204+
}
205+
167206
func configureHost(h host.Model) {
168207
err := jobqueue.AddJob(jobqueue.Job{
169208
Name: "NginxConfigureHost",

backend/internal/api/handler/upstreams.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,45 @@ func DeleteUpstream() func(http.ResponseWriter, *http.Request) {
117117
}
118118
}
119119

120+
// GetHostNginxConfig will return a Host's nginx config from disk
121+
// Route: GET /upstreams/{upstreamID}/nginx-config
122+
// Route: GET /upstreams/{upstreamID}/nginx-config.txt
123+
func GetUpstreamNginxConfig(format string) func(http.ResponseWriter, *http.Request) {
124+
return func(w http.ResponseWriter, r *http.Request) {
125+
var err error
126+
var upstreamID int
127+
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
128+
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
129+
return
130+
}
131+
132+
item, err := upstream.GetByID(upstreamID)
133+
switch err {
134+
case sql.ErrNoRows:
135+
h.ResultErrorJSON(w, r, http.StatusNotFound, "Not found", nil)
136+
case nil:
137+
// Get the config from disk
138+
content, nErr := nginx.GetUpstreamConfigContent(item)
139+
if nErr != nil {
140+
h.ResultErrorJSON(w, r, http.StatusBadRequest, nErr.Error(), nil)
141+
return
142+
}
143+
if format == "text" {
144+
h.ResultResponseText(w, r, http.StatusOK, content)
145+
return
146+
}
147+
148+
j := struct {
149+
Content string `json:"content"`
150+
}{Content: content}
151+
152+
h.ResultResponseJSON(w, r, http.StatusOK, j)
153+
default:
154+
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
155+
}
156+
}
157+
}
158+
120159
func configureUpstream(u upstream.Model) {
121160
err := jobqueue.AddJob(jobqueue.Job{
122161
Name: "NginxConfigureUpstream",

backend/internal/api/http/responses.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ func ResultErrorJSON(w http.ResponseWriter, r *http.Request, status int, message
8181
ResultResponseJSON(w, r, status, errorResponse)
8282
}
8383

84+
// ResultResponseText will write the result as text to the http output
85+
func ResultResponseText(w http.ResponseWriter, r *http.Request, status int, content string) {
86+
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
87+
w.WriteHeader(status)
88+
fmt.Fprint(w, content)
89+
}
90+
8491
// getPrettyPrintFromContext returns the PrettyPrint setting
8592
func getPrettyPrintFromContext(r *http.Request) bool {
8693
pretty, ok := r.Context().Value(c.PrettyPrintCtxKey).(bool)

backend/internal/api/router.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ func applyRoutes(r chi.Router) chi.Router {
168168
Post("/", handler.CreateHost())
169169
r.With(middleware.Enforce(user.CapabilityHostsManage)).With(middleware.EnforceRequestSchema(schema.UpdateHost())).
170170
Put("/{hostID:[0-9]+}", handler.UpdateHost())
171+
r.With(middleware.Enforce(user.CapabilityHostsManage)).Get("/{hostID:[0-9]+}/nginx-config", handler.GetHostNginxConfig("json"))
172+
r.With(middleware.Enforce(user.CapabilityHostsManage)).Get("/{hostID:[0-9]+}/nginx-config.txt", handler.GetHostNginxConfig("text"))
171173
})
172174

173175
// Nginx Templates
@@ -202,6 +204,8 @@ func applyRoutes(r chi.Router) chi.Router {
202204
r.With(middleware.Enforce(user.CapabilityHostsManage)).Delete("/{upstreamID:[0-9]+}", handler.DeleteUpstream())
203205
r.With(middleware.Enforce(user.CapabilityHostsManage)).With(middleware.EnforceRequestSchema(schema.CreateUpstream())).
204206
Post("/", handler.CreateUpstream())
207+
r.With(middleware.Enforce(user.CapabilityHostsManage)).Get("/{upstreamID:[0-9]+}/nginx-config", handler.GetUpstreamNginxConfig("json"))
208+
r.With(middleware.Enforce(user.CapabilityHostsManage)).Get("/{upstreamID:[0-9]+}/nginx-config.txt", handler.GetUpstreamNginxConfig("text"))
205209
})
206210
})
207211

backend/internal/nginx/control.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,42 @@ func removeFiles(files []string) {
185185
}
186186
}
187187
}
188+
189+
// GetHostConfigContent returns nginx config as it exists on disk
190+
func GetHostConfigContent(h host.Model) (string, error) {
191+
filename := getHostFilename(h, "")
192+
if h.ErrorMessage != "" {
193+
filename = getHostFilename(h, ErrorSuffix)
194+
}
195+
if h.IsDisabled {
196+
filename = getHostFilename(h, DisabledSuffix)
197+
}
198+
if h.IsDeleted {
199+
filename = getHostFilename(h, DeletedSuffix)
200+
}
201+
202+
// nolint: gosec
203+
cnt, err := os.ReadFile(filename)
204+
if err != nil {
205+
return "", err
206+
}
207+
return string(cnt), nil
208+
}
209+
210+
// GetUpstreamConfigContent returns nginx config as it exists on disk
211+
func GetUpstreamConfigContent(u upstream.Model) (string, error) {
212+
filename := getUpstreamFilename(u, "")
213+
if u.ErrorMessage != "" {
214+
filename = getUpstreamFilename(u, ErrorSuffix)
215+
}
216+
if u.IsDeleted {
217+
filename = getUpstreamFilename(u, DeletedSuffix)
218+
}
219+
220+
// nolint: gosec
221+
cnt, err := os.ReadFile(filename)
222+
if err != nil {
223+
return "", err
224+
}
225+
return string(cnt), nil
226+
}

0 commit comments

Comments
 (0)