diff --git a/main.go b/main.go index 27a1303..3a8d816 100644 --- a/main.go +++ b/main.go @@ -150,6 +150,7 @@ func main() { "/v1/cloud", "/v1/recover", "/v1/other", + "/v1/zt", route.V2APIPath, route.V2DocPath, route.V3FilePath, diff --git a/route/v1.go b/route/v1.go index b00e9a6..0889c39 100644 --- a/route/v1.go +++ b/route/v1.go @@ -40,7 +40,7 @@ func InitV1Router() *gin.Engine { }) r.GET("/v1/recover/:type", v1.GetRecoverStorage) v1Group := r.Group("/v1") - + r.GET("/v1/zt/*url", v1.AddZerotierToken) v1Group.Use(jwt.ExceptLocalhost(func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })) { diff --git a/route/v1/zerotier.go b/route/v1/zerotier.go new file mode 100644 index 0000000..96e2946 --- /dev/null +++ b/route/v1/zerotier.go @@ -0,0 +1,73 @@ +package v1 + +import ( + "fmt" + "io/ioutil" + "net/http" + "strings" + + "github.com/gin-gonic/gin" +) + +func AddZerotierToken(c *gin.Context) { + // Read the port number from the file + w := c.Writer + r := c.Request + port, err := ioutil.ReadFile("/var/lib/zerotier-one/zerotier-one.port") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Get the request path and remove "/zt" + path := strings.TrimPrefix(r.URL.Path, "/v1/zt") + fmt.Println(path) + + // Build the target URL + targetURL := fmt.Sprintf("http://localhost:%s%s", strings.TrimSpace(string(port)), path) + + // Create a new request + req, err := http.NewRequest(r.Method, targetURL, r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Add the X-ZT1-AUTH header + authToken, err := ioutil.ReadFile("/var/lib/zerotier-one/authtoken.secret") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + req.Header.Set("X-ZT1-AUTH", strings.TrimSpace(string(authToken))) + + copyHeaders(req.Header, r.Header) + + client := http.Client{} + resp, err := client.Do(req) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer resp.Body.Close() + + copyHeaders(w.Header(), resp.Header) + + respBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Return the response to the client + w.WriteHeader(resp.StatusCode) + w.Write(respBody) +} + +func copyHeaders(destination, source http.Header) { + for key, values := range source { + for _, value := range values { + destination.Add(key, value) + } + } +}