成员
- 09
- 10
- 2
- 文章类型
- 完全原创 —— 自由转载
本文仅为技术讨论,不鼓励翘课行为
部分老师有设置5秒二维码签到的坏毛病,不能惯着他们
那么,我们的需求是:
本文将使用原生JS编写前端(没必要用框架),Golang编写后端(减少心智负担)
首先来解决后端
虽然这只是个小工具,但毕竟部署在公网,裸跑大概率会被脚本小子撅
所以随便签个证书吧,静态资源用BasicAuth意思一下,可以加个错误等待时间什么,自行发挥
Websocket部分抄样例即可,用一个channel保存二维码
前端使用
ok齐活
部分老师有设置5秒二维码签到的坏毛病,不能惯着他们
那么,我们的需求是:
- 发送者在前端扫描二维码
- 后端接收发送者获取的二维码数据,低延迟同步给接收者
- 接收者扫描前端生成的二维码
本文将使用原生JS编写前端(没必要用框架),Golang编写后端(减少心智负担)
首先来解决后端
虽然这只是个小工具,但毕竟部署在公网,裸跑大概率会被脚本小子撅
所以随便签个证书吧,静态资源用BasicAuth意思一下,可以加个错误等待时间什么,自行发挥
C-like:
//go:embed html
var html embed.FS
var hfs http.Handler
func init() {
fsys, err := fs.Sub(html, "html")
if err != nil {
panic(err)
}
hfs = http.FileServer(http.FS(fsys))
}
func handleHtml(w http.ResponseWriter, r *http.Request) {
name, passwd, ok := r.BasicAuth()
if !ok {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
w.WriteHeader(http.StatusUnauthorized)
return
}
if name != "fkqrcode" || passwd != "nopasswd" {
http.Error(w, "Fuck off!", http.StatusUnauthorized)
return
}
hfs.ServeHTTP(w, r)
}
C-like:
var qrch = make(chan string, 3)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func handleSend(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer conn.Close()
for {
_, data, err := conn.ReadMessage()
if err != nil {
log.Printf("failed to read data from %s : %v\n", r.RemoteAddr, err)
return
}
qr := string(data)
log.Println(qr)
select {
case qrch <- qr:
default:
}
}
}
func handleReceive(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer conn.Close()
for {
qr := <-qrch
err = conn.WriteMessage(websocket.TextMessage, []byte(qr))
if err != nil {
log.Printf("failed to send qr to %s : %v\n", r.RemoteAddr, err)
return
}
}
}
adapter instascan qrcode三个库
HTML:
<video id="preview"></video>
<select id="select">
</select>
<button onclick="startScan()" id="start" disabled>Start</button>
<script>
let ws = new WebSocket("wss://" + location.host + "/send");
let err = () => location.reload();
ws.onclose = err;
ws.onerror = err;
let opts = {};
let scanner = new Instascan.Scanner({ video: document.getElementById('preview') });
scanner.refractoryPeriod = 1000;
scanner.mirror = false;
scanner.addListener('scan', (content) => ws.send(content));
Instascan.Camera.getCameras()
.then((cameras) => {
if (cameras.length > 0) {
let select = document.getElementById('select');
for (camera of cameras) {
opts[camera.name] = camera;
select.appendChild(new Option(camera.name));
}
document.getElementById('start').disabled = '';
} else {
err();
}
})
.catch(err);
function startScan() {
scanner.stop()
.then(() => {
let select = document.getElementById('select');
scanner.start(opts[select.item(select.selectedIndex).text]).catch(err)
})
.catch(err);
}
</script>
HTML:
<div id="qrcode"></div>
<script>
let qrcode = new QRCode(document.getElementById("qrcode"), "https://" + location.host);
let ws = new WebSocket("wss://" + location.host + "/receive");
ws.onmessage = () => {
qrcode.clear();
qrcode.makeCode(event.data);
};
ws.onclose = location.reload();
ws.onerror = location.reload();
</script>
ok齐活
最后编辑: