最近几天写 React、配置内网穿透遇到一些坑,记录一下。


nginx proxy_pass 路径解析

location 块中,路径最后有无 / 号对解析结果影响很大,例如:

location /api/ {
    proxy_pass http://kanata.moe/;
}
location /api/ {
    proxy_pass http://kanata.moe;
}

这两种方式的解析结果是不一样的


koa2 组件 koa-body 与 koa-bodyParser 的冲突

koa-body 组件能够处理文件上传和参数传递,而 koa-bodyParser 只能处理参数

两个组件不能同时使用,否则 koa 可能不报错,但一直无响应

艰难的调试过程

  1. 前端 React 发出 ajax POST 上传文件请求,后端返回 504 响应超时
  2. 前端 Postman 模拟 POST 带参数请求,后端返回 200 处理成功
  3. 前端确认 React 中 ajax 请求代码无误
  4. 检查 nginx 代理设置与跨域设置,添加跨域选项(前后端并未发生跨域请求,删除跨域选项)
  5. 检查 koa2 路由设置正常,log 无报错,使用 console.log() 发现请求并未到达路由
  6. 检查 koa2 接收的访问参数、访问地址正常
  7. 用 console.log() 逐级排查 koa2 洋葱模型
  8. 定位到 core/init.js 中对 koa-body 和 koa-bodyParser 的引用
  9. 尝试删除对 koa-bodyParser 的引用,bug 修复成功

MySQL 触发器的编写

MySQL 触发器是个非常方便的功能,能够快速实现数据表之间的数据关联,例:

USE setu;
DROP TRIGGER IF EXISTS count_score;
# 将结束符号替换为 $$
DELIMITER $$
CREATE TRIGGER count_score AFTER INSERT ON scores FOR EACH ROW
BEGIN
    # 不能直接对 DECLARE 的变量赋值
    DECLARE newScore INT;
    # 使用 INTO 将 SELECT 结果赋值给变量
    SELECT ROUND(AVG(score)) INTO newScore FROM scores WHERE scores.picture_id = NEW.picture_id;
    UPDATE pictures SET total_score = newScore WHERE pictures.picture_id = NEW.picture_id;
END$$
# 将结束符号还原为 ;
DELIMITER ;

其中,NEW 指即将插入或已经插入的行,OLD 指即将删除或已经删除的行

数学计算函数分别有:

AVG() 求平均值
ROUND() 四舍五入取整
CEILING() 向上取整
FLOOR() 向下取整


Let’s encrypt 泛域名证书的申请

其实用 certbot 非常简单,首先安装 certbot,然后执行一条命令:

sudo certbot certonly --preferred-challenges dns --manual -d kanata.moe -d *.kanata.moe

  • certonly 仅生成证书
  • --preferred-challenges dns 选择验证方式为 dns
  • --manual 手动模式
  • -d 泛域名可以用 * 号,但主域名也必须同时作为参数

验证过程中,会要求在 dns 解析记录里添加一条 txt 解析
然后在 nginx 配置中引入证书路径即可,如:

server {
    # ...
    ssl_certificate /etc/letsencrypt/live/kanata.moe/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/kanata.moe/privkey.pem;
    # ...
}

注意: 修改与 SSL 相关的配置后,建议重启 nginx 而不是使用 nginx -s reload
可以使用 sudo systemctl restart nginx