全屏事件触发 resize 事件 我之前发现播放视频时进入全屏会闪退。奇怪的是 Chrome 和 Firefox 存在这个问题,但 Safari 正常。正因为如此对我造成了误导,没有找到问题所在。直到今天发现了这个乌龙。 拖动改变浏览器窗口大小时会造成图文排版变形,所以我监听到 resize 事件就会重新渲染页面——表现之一就是视频进入全屏时“闪退”成了非全屏窗口,video 元素被清除了,重新渲染为缩略图 img。 那么解决这个问题就是监听到 resize 事件时增加一个判断是否全屏。 is_fullscreen = () => !!( document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement... 2024-10-25
也谈网站镜像攻防 近期不少博友遇到网站被恶意镜像的问题。我在 Google 没查到自己的镜像站,不过后台发现很多来源是不良网站的访问,不确定是否跟镜像站有关,因此也谈一下这个话题。 先说结论,网站被镜像易攻难守,没有完美的解决方案。前端可以拦截正常的浏览器访问,但是拦不住爬虫;后端拦不住域名伪造。目前我做了前端拦截 + 防盗链,可以将正常访客引导到主站,但是对搜索引擎爬虫没有找到办法。 接下来从攻防两个视角来分别讨论。 攻 Nginx 实现镜像 server { listen 80; listen 443 ssl http2; #篡改域名 server_name dujun.us.kg; location / { gzip off; proxy_set_header Accept-Encoding ""; #替换网页内容... 2024-09-26
双击全选代码文本 我代码高亮是几年前参考Prism改写的,留有一个遗憾是缺失复制代码文本的功能,因为我一直没有找到理想的交互方式。常见的办法是在右上角放一个常驻或悬停可见的复制按钮,点击后自动将全文复制到剪贴板。我不认可这个设计,一是按钮造成一小块遮挡,二是移动鼠标去找一个按钮进行复制不是很自然的交互,特别是文本较长需要往上回滚的情况下。 我平时习惯双击选中一段文本,按照这个方式增加了双击全选代码文本的功能——仅全选而不自动加入剪贴板,防止误触。 $pre.on('dblclick', () => { let range = document.createRange(), selection = window.getSelection(); range.selectNodeContents($pre[0]); selection.removeAllRanges()... 2024-09-26
乱码导致 json_encode 失败的解决方法 发现访客日志缓存失效,定位到写入 redis 时数据经 json_encode 变成了空字符。调用 json_last_error_msg() 打印出报错信息为:"Malformed UTF-8 characters, possibly incorrectly encoded"。 解决办法是增加参数 JSON_INVALID_UTF8_IGNORE,过滤掉乱码字符: json_encode($value, JSON_INVALID_UTF8_IGNORE); 2024-09-19
更换天气信源 [附件] 宝宝日记后台编辑器根据定位自动获取当日天气信息。这项功能开发于 2017 年,当时选定的方案是采集中国天气网页面,通过正则表达式提取相关数据。但现在偶然发现其天气信息与墨迹天气 APP 有差别,我到中国气象局官网验证,与墨迹天气是一致的,也就是说中国天气网数据是错误的。不准确的信源毫无意义,马上决定更换。 经过对比,最终选定和风天气作为新的天气信源,免费版接口支持每天1000次请求。 注册 在官网注册账号(需要邮箱和手机号),创建一个免费订阅,记录 KEY 值。 调用 详见文档:https://dev.qweather.com/docs/api/weather/weather-daily-forecast/ 接口调用 PHP 代码参考: declare(strict_types = 1); /** * 天气 (和风天气) */ class Vendor_Weather { //... 2024-09-11
第一次体验 AI 自然语言编程 我是一个上了年纪的守旧的程序员。现在也开始依赖 AI 工具,主要是翻译、做图、查一些代码语法和示例。但我从未尝试直接用 AI 写代码,或许这是在自己专业领域被挑战的防御心理,一种莫名的排斥。不过今晚破例了,因为我要写一个 shell 代码,而我不熟练,所以抱着试试看的心态,用自然语言向 AI 提了需求。我的提问内容是: 用shell 代码实现下列功能: 接收一个输入值作为用户名,记为 name。 生成一个 10000 到 65535 之间的随机数作为端口号,记为 port,如果当前目录下有子目录名末尾含这个 port,则重新生成一次。 最终的目录名为 www_slim_web_ + name + _ + port。 创建这个目录,进入这个目录并创建一个 docker-compose.yml,模版为: version: '2.4' services: web: image: du... 2024-06-27
frp 服务守护脚本 为了方便开发,我将工控机从公司拿回了家里。在未做任何修改的情况下,原先在公司很稳定的内网穿透,到了家里不定期地就会断开连接——frp 进程未死,但是穿透代理全部关闭。研究了几天也没解决,现在只能推测是家庭宽带不如企业宽带稳定。(家宽故意干扰长连接?限制内网穿透?) 我用守护脚本临时解决这个问题。思路是每分钟检查内网穿透出的 web 服务可用性(http 状态码 为 200),不可用则杀死进程,然后再由 Supervisor 自动拉起服务。另外写入标记文件,避免重复杀进程。脚本如下: #!/bin/bash URL="https://dujun.bf" TIME=`date "+%Y-%m-%d %H:%M:%S"` FAIL_LOG_FILE="/var/log/frp/failed_$(date '+%Y%m%d').log" FLAG_FILE="/var/log/frp/flag_$... 2024-04-11
开源实例之Gunicorn 前言 本篇介绍《开源实例之FlaskBB》中提到的 Gunicorn。 Gunicorn介绍 Gunicorn is a Python WSGI HTTP Server for UNIX. It's a pre-fork worker model ported from Ruby's Unicorn project. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resources, and fairly speedy. Gunicorn(Green Unicorn)是一个 Python WSGI(Web Server Gateway Interface)HTTP 服务器。因为 Nginx 不能直接支持 WSGI 协议,所以... 2023-03-27
开源实例之页面劫持 前言 本篇介绍用 Nginx sub_filter 实现拦截页面替换内容。 问题描述 本系列的实例为了使用方便,登录页默认填充了用户名和密码。一般是通过修改相关 HTML 或 JS 文件实现,但也有的实例做成了二进制包,要用页面劫持的方式注入,比如护卫神主机大师这个实例。 护卫神·主机大师 V3.0.0 实例的登录页面使用了 VUE 框架,需要劫持/static/js/chunk-common.062e7d64.js这个文件,填充username和password: data() { return {form: {username: "", password: ""}} } 解决办法 本例用 Nginx sub_filter 方法实现。 sub_filter 执行nginx -V如果包含--with-http_sub_module表明已安装 sub_filter 对应的模块。Deb... 2023-03-14
php 双问号可以链式使用 刚才改网站代码,偶然发现 php 双问号是可以链式使用的: $ret = $a ?? $b ?? $c ?? 4; 原本我是应该加括号的: $ret = $a ?? ($b ?? ($c ?? 4)); 无心之失忘了加括号,竟然可以执行,才发现双问号可以链式使用。 之所以有这样的乌龙,是因为我这个从 php5 时代入行的古典程序员,对新的语法糖是想当然的,没有去仔细看过文档。双问号的使用习惯也是从三元式演变过来的,自然没想过还能链式使用。 用三元式表达上面的语句是这样的: $ret = isset($a) ? $a : (isset($b) ? $b : (isset($c) ? $c : 4)); php 不愧是世界上最好的语言。令人开心。 2022-11-11