在分享一些github上面的releases文件资源的时候,github的下载链接有时候速度很慢。所以我自己服务器存一份,在自己服务器的下载会快一些。但是github上面更新了版本,我这还得在我服务器上也更新文件和下载地址,有些烦。所以我想实现nginx获取我的链接去github上下载再转手给我,相当于一个代理。

准备工作

一个服务器:此处示例是Debian 12
一个网站:搭建参考https://evlan.cc/archives/docker-nginx.html

安装http客户端

主要用到的文件就是这三个文件

QQ20241010-220839.jpg

  • http_headers.lua
  • http_connect.lua
  • http.lua

获取软件包

先在服务器上下载软件包

wget https://github.com/ledgetech/lua-resty-http/archive/refs/tags/v0.17.2.zip
# 解压 如果unzip命令未找到就安装解压软件`apt install unzip -y`
unzip v0.17.2.zip

复制文件到nginx容器内

假如按照我之前教程搭建的nginx,映射目录应该有一个/home/www,docker容器内和宿主机都能访问,所以把文件放这

cp lua-resty-http-0.17.2/lib/resty/http*lua /home/www

进入容器并把文件放到指定位置完成安装

# 进入容器
docker exec -it nginx sh
# 转移文件
mv /home/www/http*lua /usr/local/openresty/lualib/resty/
# 退出容器
exit

写代码

代码流程就是通过路径获取下载连接,然后发起请求去下载,把取得的数据原封不动的返回给请求者

找到配置文件,加上下面这个location代码块

    location /download/ {
        resolver 8.8.8.8;  # DNS解析
        content_by_lua_block {
            local ngx = require "ngx"
            local http = require "resty.http"
            local target_url = "https://github.com/" .. ngx.var.uri:gsub("^/download/", "")
            local res, err
            
            if not target_url or target_url == "" then
                ngx.status = ngx.HTTP_BAD_REQUEST
                ngx.say("Missing or invalid parameter")
                return
            end
            
            local function parse_url(url)
                local _, scheme, host, path = url:match("^((https?)://([^/]+))(/.*)$")
                return scheme, host, path
            end
            
            local http_client = http.new()
            local max_redirects = 5
            local redirect_count = 0
            
            repeat
                if redirect_count > max_redirects then
                    ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
                    ngx.say("Too many redirects")
                    return
                end
            
                local scheme, host, path = parse_url(target_url)
            
                local ok, e = http_client:connect({ scheme = scheme, host = host, ssl_verify = false })
            
                if not ok then
                    ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
                    ngx.say("connection failed: ", e)
                    return
                end
            
                res, err = http_client:request({ path = path })
                if not res then
                    ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
                    ngx.say("request failed: ", err)
                    return
                end
            
                if res.status == ngx.HTTP_MOVED_PERMANENTLY or res.status == ngx.HTTP_MOVED_TEMPORARILY then
                    target_url = res.headers["Location"]
                    if not target_url then
                        target_url = res.headers["location"]
                        if not target_url then
                            ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
                            ngx.say("Redirect without location header")
                            return
                        end
                    end
                end
            
                redirect_count = redirect_count + 1
            until (res.status ~= ngx.HTTP_MOVED_PERMANENTLY and res.status ~= ngx.HTTP_MOVED_TEMPORARILY)
            
            -- 复制响应头
            for k, v in pairs(res.headers) do
                if k:lower() ~= "content-encoding" and k:lower() ~= "transfer-encoding" then
                    ngx.header[k] = v
                end
            end
            
            ngx.status = res.status
            
            local reader = res.body_reader
            local buffer_size = 8192
            local buffer
            
            repeat
                buffer, err = reader(buffer_size)
                if err then
                    ngx.log(ngx.ERR, err)
                    break
                end
            
                if buffer then
                    ngx.print(buffer)
                    ngx.flush(true)
                end
            until not buffer
            http_client:close()
            return
        }
    }

加上之后代码之后重启nginx生效

docker restart nginx

使用

比如我的网站是https://xxx.com,我想下载https://github.com/ledgetech/lua-resty-http/archive/refs/tags/v0.17.2.zip,此时我只需要访问https:/xxx.com/download/ledgetech/lua-resty-http/archive/refs/tags/v0.17.2.zip,就能通过我的https://xxx.com网站的服务器做中转下载。

修改

这里只是下载github文件,其实可以可以不仅限这一个域名,只要稍微修改

            local target_url = "https://github.com/" .. ngx.var.uri:gsub("^/download/", "")

这一行改成

            local target_url = "https://" .. ngx.var.uri:gsub("^/download/", "")

然后下载文件只需要下载地址开头的https://换成https:/xxx.com/download/即可,
此时下载https://github.com/ledgetech/lua-resty-http/archive/refs/tags/v0.17.2.zip,就需要访问https:/xxx.com/download/github.com/ledgetech/lua-resty-http/archive/refs/tags/v0.17.2.zip

标签: Nginx, Lua, Openresty

添加新评论

Loading...
Fullscreen Image