13497: Move common system service code to lib/service.
[arvados.git] / lib / controller / handler.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package controller
6
7 import (
8         "io"
9         "net/http"
10         "net/url"
11         "sync"
12
13         "git.curoverse.com/arvados.git/sdk/go/arvados"
14         "git.curoverse.com/arvados.git/sdk/go/health"
15 )
16
17 type Handler struct {
18         Cluster *arvados.Cluster
19
20         setupOnce    sync.Once
21         handlerStack http.Handler
22         proxyClient  *arvados.Client
23 }
24
25 func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
26         h.setupOnce.Do(h.setup)
27         h.handlerStack.ServeHTTP(w, req)
28 }
29
30 func (h *Handler) setup() {
31         mux := http.NewServeMux()
32         mux.Handle("/_health/", &health.Handler{
33                 Token:  h.Cluster.ManagementToken,
34                 Prefix: "/_health/",
35         })
36         mux.Handle("/", http.HandlerFunc(h.proxyRailsAPI))
37         h.handlerStack = mux
38 }
39
40 func (h *Handler) proxyRailsAPI(w http.ResponseWriter, incomingReq *http.Request) {
41         url, err := findRailsAPI(h.Cluster)
42         if err != nil {
43                 http.Error(w, err.Error(), http.StatusInternalServerError)
44                 return
45         }
46         req := *incomingReq
47         req.URL.Host = url.Host
48         resp, err := arvados.InsecureHTTPClient.Do(&req)
49         if err != nil {
50                 http.Error(w, err.Error(), http.StatusInternalServerError)
51                 return
52         }
53         for k, v := range resp.Header {
54                 for _, v := range v {
55                         w.Header().Add(k, v)
56                 }
57         }
58         w.WriteHeader(resp.StatusCode)
59         io.Copy(w, resp.Body)
60 }
61
62 // For now, findRailsAPI always uses the rails API running on this
63 // node.
64 func findRailsAPI(cluster *arvados.Cluster) (*url.URL, error) {
65         node, err := cluster.GetThisSystemNode()
66         if err != nil {
67                 return nil, err
68         }
69         return url.Parse("http://" + node.RailsAPI.Listen)
70 }