-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
171 lines (151 loc) · 4.37 KB
/
Copy pathmain.go
File metadata and controls
171 lines (151 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// 文件传输 — 局域网文件共享与直传工具
//
// 两种模式:
// 1. 共享模式 - 上传到服务器,局域网内设备均可下载(文件持久化)
// 2. 直传模式 - 上传后即时转发给指定设备,对方自动下载,文件不保留
//
// 设备通过 localStorage 中持久化的设备 ID 自动识别,无需手动输入 token。
// 数据明文 HTTP 传输,面向信任局域网环境。
package main
import (
"embed"
"flag"
"fmt"
"log"
"net"
"net/http"
"os"
"strings"
)
//go:embed static/*
var staticFS embed.FS
func main() {
port := flag.String("port", "8080", "server port")
flag.Parse()
os.MkdirAll("uploads", 0755)
serverAddr := getLanIP(*port)
h := NewHandler("uploads")
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
switch {
case path == "/api/events" && r.Method == "GET":
h.sseEvents(w, r)
case path == "/api/devices" && r.Method == "GET":
h.listDevices(w, r)
case path == "/api/name" && r.Method == "POST":
h.setName(w, r)
case path == "/api/send" && r.Method == "POST":
h.sendFile(w, r)
case path == "/api/files" && r.Method == "GET":
h.listFiles(w, r)
case path == "/api/upload" && r.Method == "POST":
h.uploadFile(w, r)
case strings.HasPrefix(path, "/api/download/") && r.Method == "GET":
h.downloadFile(w, r)
case strings.HasPrefix(path, "/api/inbox/") && r.Method == "GET":
h.serveInbox(w, r)
default:
serveStaticFile(w, r, serverAddr)
}
})
printAccessInfo(*port, serverAddr)
log.Fatal(http.ListenAndServe(":"+*port, mux))
}
func serveStaticFile(w http.ResponseWriter, r *http.Request, serverAddr string) {
path := r.URL.Path
if path == "/" {
path = "/index.html"
}
data, err := staticFS.ReadFile("static" + path)
if err != nil {
data, _ = staticFS.ReadFile("static/index.html")
}
if strings.HasSuffix(path, ".html") {
data = []byte(strings.Replace(string(data), "__SERVER_ADDR__", serverAddr, 1))
}
switch {
case strings.HasSuffix(path, ".css"):
w.Header().Set("Content-Type", "text/css; charset=utf-8")
case strings.HasSuffix(path, ".js"):
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
default:
w.Header().Set("Content-Type", "text/html; charset=utf-8")
}
w.Write(data)
}
func getLanIP(port string) string {
ip := pickBestIP()
if ip == "" {
return fmt.Sprintf("http://localhost:%s", port)
}
return fmt.Sprintf("http://%s:%s", ip, port)
}
func isPrivateIP(ip net.IP) bool {
return ip[0] == 10 ||
(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) ||
(ip[0] == 192 && ip[1] == 168)
}
func isLinkLocal(ip net.IP) bool {
return ip[0] == 169 && ip[1] == 254
}
func pickBestIP() string {
addrs, _ := net.InterfaceAddrs()
var firstPrivate, firstOther string
for _, addr := range addrs {
ipnet, ok := addr.(*net.IPNet)
if !ok {
continue
}
ip4 := ipnet.IP.To4()
if ip4 == nil || ip4.IsLoopback() || isLinkLocal(ip4) {
continue
}
s := ip4.String()
if isPrivateIP(ip4) {
if firstPrivate == "" {
firstPrivate = s
}
} else {
if firstOther == "" {
firstOther = s
}
}
}
if firstPrivate != "" {
return firstPrivate
}
return firstOther
}
func printAccessInfo(port, serverAddr string) {
fmt.Println()
fmt.Println(" ╔══════════════════════════════════════╗")
fmt.Println(" ║ 📁 文件传输服务 已启动 ║")
fmt.Println(" ╠══════════════════════════════════════╣")
best := pickBestIP()
addrs, _ := net.InterfaceAddrs()
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok {
if ip4 := ipnet.IP.To4(); ip4 != nil && !ip4.IsLoopback() {
marker := " "
if ip4.String() == best {
marker = "★ "
}
addrStr := fmt.Sprintf("%shttp://%s:%s", marker, ip4, port)
pad := 32 - len(addrStr)
if pad < 1 {
pad = 1
}
fmt.Printf(" ║ %s%s║\n", addrStr, strings.Repeat(" ", pad))
}
}
}
addrStr := fmt.Sprintf("http://localhost:%s", port)
pad := 30 - len(addrStr)
if pad < 1 {
pad = 1
}
fmt.Printf(" ║ %s%s║\n", addrStr, strings.Repeat(" ", pad))
fmt.Println(" ╚══════════════════════════════════════╝")
fmt.Println()
}