proxyRequestToLocalAPI proxies the web API request to the localapi. The web API request path is expected to exactly match a localapi path, with prefix /api/local/ rather than /localapi/.
(w http.ResponseWriter, r *http.Request)
| 1276 | // The web API request path is expected to exactly match a localapi path, |
| 1277 | // with prefix /api/local/ rather than /localapi/. |
| 1278 | func (s *Server) proxyRequestToLocalAPI(w http.ResponseWriter, r *http.Request) { |
| 1279 | path := strings.TrimPrefix(r.URL.Path, "/api/local") |
| 1280 | if r.URL.Path == path { // missing prefix |
| 1281 | http.Error(w, "invalid request", http.StatusBadRequest) |
| 1282 | return |
| 1283 | } |
| 1284 | |
| 1285 | switch path { |
| 1286 | case "/v0/logout": |
| 1287 | if !s.getPeer(r.Context()).canEdit(capFeatureAccount) { |
| 1288 | http.Error(w, "not allowed", http.StatusUnauthorized) |
| 1289 | return |
| 1290 | } |
| 1291 | case "/v0/update/check": |
| 1292 | if r.Method == httpm.POST && !s.getPeer(r.Context()).canEdit(capFeatureAccount) { |
| 1293 | http.Error(w, "not allowed", http.StatusUnauthorized) |
| 1294 | return |
| 1295 | } |
| 1296 | } |
| 1297 | |
| 1298 | localAPIURL := "http://" + apitype.LocalAPIHost + "/localapi" + path |
| 1299 | req, err := http.NewRequestWithContext(r.Context(), r.Method, localAPIURL, r.Body) |
| 1300 | if err != nil { |
| 1301 | http.Error(w, "failed to construct request", http.StatusInternalServerError) |
| 1302 | return |
| 1303 | } |
| 1304 | |
| 1305 | // Make request to tailscaled localapi. |
| 1306 | resp, err := s.lc.DoLocalRequest(req) |
| 1307 | if err != nil { |
| 1308 | http.Error(w, err.Error(), resp.StatusCode) |
| 1309 | return |
| 1310 | } |
| 1311 | defer resp.Body.Close() |
| 1312 | |
| 1313 | // Send response back to web frontend. |
| 1314 | w.Header().Set("Content-Type", resp.Header.Get("Content-Type")) |
| 1315 | w.WriteHeader(resp.StatusCode) |
| 1316 | if _, err := io.Copy(w, resp.Body); err != nil { |
| 1317 | http.Error(w, err.Error(), http.StatusInternalServerError) |
| 1318 | } |
| 1319 | } |
| 1320 | |
| 1321 | // enforcePrefix returns a HandlerFunc that enforces a given path prefix is used in requests, |
| 1322 | // then strips it before invoking h. |