serveAPI serves requests for the web client api. It should only be called by Server.ServeHTTP, via Server.apiHandler, which protects the handler using gorilla csrf.
(w http.ResponseWriter, r *http.Request)
| 581 | // It should only be called by Server.ServeHTTP, via Server.apiHandler, |
| 582 | // which protects the handler using gorilla csrf. |
| 583 | func (s *Server) serveAPI(w http.ResponseWriter, r *http.Request) { |
| 584 | if r.Method == httpm.PATCH { |
| 585 | // Enforce that PATCH requests are always application/json. |
| 586 | if ct := r.Header.Get("Content-Type"); ct != "application/json" { |
| 587 | http.Error(w, "invalid request", http.StatusBadRequest) |
| 588 | return |
| 589 | } |
| 590 | } |
| 591 | |
| 592 | var err error |
| 593 | r, err = s.setPeer(r) |
| 594 | if err != nil { |
| 595 | http.Error(w, err.Error(), http.StatusUnauthorized) |
| 596 | return |
| 597 | } |
| 598 | |
| 599 | path := strings.TrimPrefix(r.URL.Path, "/api") |
| 600 | switch { |
| 601 | case path == "/data" && r.Method == httpm.GET: |
| 602 | s.serveGetNodeData(w, r) |
| 603 | return |
| 604 | case path == "/exit-nodes" && r.Method == httpm.GET: |
| 605 | s.serveGetExitNodes(w, r) |
| 606 | return |
| 607 | case path == "/routes" && r.Method == httpm.POST: |
| 608 | handleJSON[postRoutesRequest](s.servePostRoutes)(w, r) |
| 609 | return |
| 610 | case path == "/device-details-click" && r.Method == httpm.POST: |
| 611 | s.serveDeviceDetailsClick(w, r) |
| 612 | return |
| 613 | case path == "/local/v0/logout" && r.Method == httpm.POST: |
| 614 | s.proxyRequestToLocalAPI(w, r) |
| 615 | return |
| 616 | case path == "/local/v0/prefs" && r.Method == httpm.PATCH: |
| 617 | handleJSON[maskedPrefs](s.serveUpdatePrefs)(w, r) |
| 618 | return |
| 619 | case path == "/local/v0/update/check" && r.Method == httpm.GET: |
| 620 | s.proxyRequestToLocalAPI(w, r) |
| 621 | return |
| 622 | case path == "/local/v0/update/check" && r.Method == httpm.POST: |
| 623 | s.proxyRequestToLocalAPI(w, r) |
| 624 | return |
| 625 | case path == "/local/v0/update/progress" && r.Method == httpm.POST: |
| 626 | s.proxyRequestToLocalAPI(w, r) |
| 627 | return |
| 628 | case path == "/local/v0/upload-client-metrics" && r.Method == httpm.POST: |
| 629 | s.proxyRequestToLocalAPI(w, r) |
| 630 | return |
| 631 | } |
| 632 | http.Error(w, "invalid endpoint", http.StatusNotFound) |
| 633 | } |
| 634 | |
| 635 | type authResponse struct { |
| 636 | ServerMode ServerMode `json:"serverMode"` |