博客

  • 使用Caddy反向代理WordPress

    具体配置

    xxx.xxxx.xxx {
        tls youremail@yourmailserver
    
        root * /path/to/wordpress
    
        # GZIP和FPM配置
        encode gzip
        file_server
        php_fastcgi php:9000
    
        # 静态文件配置
        @static_files {
            path_regexp \.(?:css|js|woff2?|svg|gif|map|png|jpg|webp|gif|jpeg|mp4|mp3|wav|mov|heic)
        }
        header @static_files {
            Cache-Control "public, max-age=15778463"
            X-Robots-Tag "none"
            X-Permitted-Cross-Domain-Policies "none"
            X-Frame-Options "SAMEORIGIN"
            X-Download-Options "noopen"
            X-Content-Type-Options "nosniff"
            # Referrer-Policy "no-referrer"
        }
    
        # 禁止访问的目录/文件
        @disallowed {
            #path /wp-cron.php
            #path /xmlrpc.php
            path *.sql
            path /wp-content/uploads/*.php
            path /wp-content/uploads/*.html
            path /wp-content/debug.log
        }
        rewrite @disallowed =404
    }
  • 美林投资时钟

    美林投资时钟

    美林时钟库存周期经济表现
    复苏期被动去库存经济↑,通货膨胀↓,商场需求↑
    生产未及时跟进,库存↓
    过热期主动补库存经济↑,通货膨胀↑,市场需求↑
    生产未及时跟进,库存↑
    滞涨期被动补库存经济↓,通货膨胀↑,市场需求↓
    生产未及时跟进,库存↑
    衰退期主动去库存经济↓,通货膨胀↓,市场需求↓
    生产未及时跟进,库存↓
    美林时钟

  • 函数计算WordPress实例预热程序

    函数计算有冷启动的问题,如果启用VPC,还有VPC的启动时间,为了避免冷启动问题,可以通过预热程序来避免函数实例被销毁。此预热程序示例使用Cloudflare Worker,正好同时用预热程序支持Wordpress的定时任务。

    (更多…)
  • 构建WordPress插件、主题开发镜像

    构建PHP镜像

    PHP内置服务器的路由脚本可以参考这个链接:使用PHP内置服务器运行WORDPRESS

    FROM php:8.1.27-alpine
    RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
    && mkdir /code \
    && docker-php-ext-install mysqli
    CMD [ "php", "-S", "0.0.0.0:8080", "-t", "/code", "/code/router.php" ]

    配置compose

    version: "3"
    services:
      wordpress:
        build: .
        volumes:
          - /Users/ianzhi/Code/php/wordpress:/code
        restart: always
        ports:
          - 8080:8080
      mysql:
        image: mysql:8.0.36
        environment:
          MYSQL_ROOT_PASSWORD: 'root'
        expose:
          - 3306
        ports:
          - 3306:3306
    
  • 软著申请

    软著申请在中国版权保护中心,记录一下具体的要求细节,更具体的信息参考:计算机软件著作权登记指南

    (更多…)
  • MySQL创建分区表相关

    背景:一个记录表,类似日志的信息,查询大量集中在某个用户个人的数据,分区需要尽量保证一个人的数据在一个分区里。因此采用通过user_id进行hash分区的方式。

    (更多…)
  • MySQL多层级树形结构表的搜索查询优化

    业务中有思维导图的功能,涉及到大量的树形结构搜索、查询相关的功能,使用场景上查询量远高于增删改操作,记录一下当前的解决方案。

    (更多…)
  • 使用WordPress作为小程序后端——APPID有效性前置检查

    上一篇实现了一个简单的前置检查,这一篇我们来聊一聊如何实现APPID的有效性检查。上一篇中,我们只是简单的将APPID获取到并传递到了请求处理函数中,这一篇,我们来实现一个APPID有效性的前置检查,或者叫中间件。

    APPID的检查相对比较简单,我们可以透过一种比较Wordpress的方式来实现:

    add_filter('wechat_mp_permission_callback', function ($permission, WP_REST_Request $request) {
        if ($permission === false) {
            return false;
        }
    
        $wechat_mp_apps = apply_filters( 'wechat_mp_apps', [] );
        $attrs = $request->get_attributes();
        return array_key_exists($attrs['app_id'], $wechat_mp_apps);
    }, 10, 2);

  • 使用WordPress作为小程序后端——小程序请求前置检查

    小程序默认提供了一个固定格式的referer格式,具体可以参考官方文档:网络请求。如下:

    https://servicewechat.com/{appid}/{version}/page-frame.html

    由于这个referer是不可以手动设置的,因此透过这个referer,我们可以对请求进行一个简单的前置检查,过滤一些简单的脚本。同时,我们也能通过这个前置检查来了解请求的身份,即小程序APPID,当需要同时支持多个小程序时,这一点还是很有意义的。

    一个简单实现

    /**
     * 小程序请求通用前置检查
     */
    function precheck($referer) {
        $result = preg_match("/^https:\/\/servicewechat\.com\/(.*?)\/(.*?)\/page-frame\.html$/", $referer, $matches);
        if (!$result || empty($matches) || !isset($matches[1]) || !isset($matches[2])) {
            return false;
        }
    
        return true;
    }

    在Wordpress中的使用

    通过这个简单的函数,我们可以对小程序发起的请求进行一个简单的前置检查。那么如何应用到Wordpress中呢?

    通过阅读Wordpress的文档,可以了解注册rest路由的函数是register_rest_route,具体参考文档:register_rest_route。注册路由可以配置三个回调函数,分别是permission_callback,validate_callback和callback。我觉得这个检查更适合用在permission_callback,即当无法通过检查的时候,我们实际上可以认为这是一个非法请求,我们对之前的实现进行一些修改:

    /**
     * 小程序请求通用前置检查
     */
    function precheck(WP_REST_Request $request) {
        $referer = $request->get_header('referer');
        $result = preg_match("/^https:\/\/servicewechat\.com\/(.*?)\/(.*?)\/page-frame\.html$/", $referer, $matches);
        if (!$result || empty($matches) || !isset($matches[1]) || !isset($matches[2])) {
            return false;
        }
    
        return true;
    }

    暂存获取到的APPID和VERSION,方便之后使用

    在前面的代码里,我们通过一个简单的正则,对referer进行了一个简单的检查,但是匹配的一些结果我们没有暂存下来,为了方便之后获取APPID和VERSION信息,我们再次扩展一下:

    /**
     * 小程序请求通用前置检查
     */
    function precheck(WP_REST_Request $request) {
        $referer = $request->get_header('referer');
        $result = preg_match("/^https:\/\/servicewechat\.com\/(.*?)\/(.*?)\/page-frame\.html$/", $referer, $matches);
        if (!$result || empty($matches) || !isset($matches[1]) || !isset($matches[2])) {
            return false;
        }
    
        $request->set_attributes([
            'app_id' => $matches[1],
            'version' => $matches[2]
        ]);
    
        return true;
    }

    封装

    为了更方便使用,我们再次进行一点简单的封装。

    /**
     * 给所有的路由添加默认的前置检查钩子
     */
    function register_wechat_mp_rest_route($route_namespace, $route, $args = [], $override = false) {
        add_filter( 'wechat_mp_permission_callback', precheck, 10, 2 );
    
        if (isset($args['permission_callback'])) {
            if (!is_array($args['permission_callback'])) {
                $args['permission_callback'] = [ $args['permission_callback'] ];
            }
    
            foreach ($args['permission_callback'] as $callback) {
                add_filter( 'wechat_mp_permission_callback', $callback, 10 , 2 );
            } 
        }
        $args['permission_callback'] = function (WP_REST_Request $request) {
            return apply_filters( 'wechat_mp_permission_callback', true, $request );
        };
        return register_rest_route($route_namespace, $route, $args, $override);
    }
    
    /**
     * 小程序请求通用前置检查
     */
    function precheck($permission, WP_REST_Request $request) {
        if ($permission === false) {
            return false;
        }
    
        $referer = $request->get_header('referer');
        $result = preg_match("/^https:\/\/servicewechat\.com\/(.*?)\/(.*?)\/page-frame\.html$/", $referer, $matches);
        if (!$result || empty($matches) || !isset($matches[1]) || !isset($matches[2])) {
            return false;
        }
    
        $request->set_attributes([
            'app_id' => $matches[1],
            'version' => $matches[2]
        ]);
    
        return true;
    }

    好,到这里,我们的前置检查相关的代码就完成了。下一篇的时候我们来实现一下用户认证。

  • Windows rclone挂载sftp

    手动挂载命令:

    rclone mount sftp:/mnt o: --cache-dir %SystemRoot%\TEMP --allow-other --vfs-cache-mode writes --vfs-cache-max-age 60s  --allow-non-empty

    创建服务:

    // 安装nssm
    winget install nssm
    
    // 创建服务
    nssm install rclone

    配置信息(具体路径需要根据实际情况来确定):

    Path: C:\Users\Administrator\Documents\bin\rclone.exe
    Arguments: mount config:/root A: --volname sftp --config C:\Users\Administrator\AppData\Roaming\rclone\rclone.conf

    遇到的问题

    1. 无法修改文件

    是因为nssm默认使用LocalSystem用户。

    任务管理器-服务-右键rclone选择打开服务->找到rclone右键选择属性->登录->选择此账户->点击右侧浏览->弹出框中选择高级->立即查找->选择一个本地账户比如Adminstrator->一路确定。