MakeExternalAPI turns a util.JSONRequestHandler function into an http.Handler. This is used for APIs that are called from the internet.
(metricsName string, f func(*http.Request) util.JSONResponse)
| 87 | // MakeExternalAPI turns a util.JSONRequestHandler function into an http.Handler. |
| 88 | // This is used for APIs that are called from the internet. |
| 89 | func MakeExternalAPI(metricsName string, f func(*http.Request) util.JSONResponse) http.Handler { |
| 90 | // TODO: We shouldn't be directly reading env vars here, inject it in instead. |
| 91 | // Refactor this when we split out config structs. |
| 92 | verbose := false |
| 93 | if os.Getenv("DENDRITE_TRACE_HTTP") == "1" { |
| 94 | verbose = true |
| 95 | } |
| 96 | h := util.MakeJSONAPI(util.NewJSONRequestHandler(f)) |
| 97 | withSpan := func(w http.ResponseWriter, req *http.Request) { |
| 98 | nextWriter := w |
| 99 | if verbose { |
| 100 | logger := logrus.NewEntry(logrus.StandardLogger()) |
| 101 | // Log outgoing response |
| 102 | rec := httptest.NewRecorder() |
| 103 | nextWriter = rec |
| 104 | defer func() { |
| 105 | resp := rec.Result() |
| 106 | dump, err := httputil.DumpResponse(resp, true) |
| 107 | if err != nil { |
| 108 | logger.Debugf("Failed to dump outgoing response: %s", err) |
| 109 | } else { |
| 110 | strSlice := strings.Split(string(dump), "\n") |
| 111 | for _, s := range strSlice { |
| 112 | logger.Debug(s) |
| 113 | } |
| 114 | } |
| 115 | // copy the response to the client |
| 116 | for hdr, vals := range resp.Header { |
| 117 | for _, val := range vals { |
| 118 | w.Header().Add(hdr, val) |
| 119 | } |
| 120 | } |
| 121 | w.WriteHeader(resp.StatusCode) |
| 122 | // discard errors as this is for debugging |
| 123 | _, _ = io.Copy(w, resp.Body) |
| 124 | _ = resp.Body.Close() |
| 125 | }() |
| 126 | |
| 127 | // Log incoming request |
| 128 | dump, err := httputil.DumpRequest(req, true) |
| 129 | if err != nil { |
| 130 | logger.Debugf("Failed to dump incoming request: %s", err) |
| 131 | } else { |
| 132 | strSlice := strings.Split(string(dump), "\n") |
| 133 | for _, s := range strSlice { |
| 134 | logger.Debug(s) |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | span := opentracing.StartSpan(metricsName) |
| 140 | defer span.Finish() |
| 141 | req = req.WithContext(opentracing.ContextWithSpan(req.Context(), span)) |
| 142 | h.ServeHTTP(nextWriter, req) |
| 143 | |
| 144 | } |
| 145 | |
| 146 | return http.HandlerFunc(withSpan) |