You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何部分URL浏览器可正常访问,使用Lua的http(s).request却请求失败

问题原因分析

你遇到的问题是由以下几个常见原因导致的,均和ssl.https的默认配置限制有关:

  • TLS SNI扩展缺失:ics.fixtur.es使用多域名共享IP的HTTPS部署方案,要求客户端在TLS握手阶段发送SNI(服务器名称指示)扩展才能正确获取站点证书、完成TLS握手。而ssl.https默认配置下不会主动发送SNI,Google日历的HTTPS服务对旧客户端兼容性更强,不需要SNI也能正常响应,因此只有B链接可以正常返回结果。
  • User-Agent校验限制:部分服务端会拦截默认的LuaSocket类爬虫UA、或者UA为空的请求,直接拒绝返回内容。
  • TLS版本限制:ics.fixtur.es可能已经禁用了安全性较低的TLS 1.0/1.1版本,如果你使用的Lua ssl库默认协商的TLS版本过低,也会导致TLS握手失败。

你提到的redirect配置用法如下:该参数接收布尔值,设为true时请求会自动跟随3xx重定向响应(默认即为开启状态),设为false时会直接返回重定向的状态码和响应头,不会自动跳转。你已经排查过目标链接无重定向,因此该参数不是导致当前问题的原因。

解决方法

你可以通过自定义请求参数、补充SNI配置、添加合法UA头来解决问题,修改后的测试代码如下:

local socket = require 'socket'
local http = require "socket.http"
local ssl = require 'ssl'
local https = require 'ssl.https'
local ltn12 = require 'ltn12'

local calendarUria = "https://ics.fixtur.es/v2/ipswich-town.ics"
local calendarUrib = "https://calendar.google.com/calendar/ical/en-gb.uk%23holiday%40group.v.calendar.google.com/public/basic.ics"

-- 自定义支持SNI的create函数
local function create()
    local sock = socket.tcp()
    return setmetatable({
        connect = function(_, host, port)
            local ok, err = sock:connect(host, port)
            if not ok then return nil, err end
            -- TLS握手时添加SNI扩展
            sock = ssl.wrap(sock, {
                mode = 'client',
                protocol = 'any', -- 自动协商最高支持的TLS版本
                options = {'all', 'no_sslv2', 'no_sslv3', 'no_tlsv1', 'no_tlsv1_1'}, -- 禁用不安全的旧协议
                verify = 'none', -- 如果需要校验证书可以改为'peer',同时配置cafile
            })
            sock:sni(host)
            return sock:dohandshake()
        end
    }, {
        __index = function(t, n)
            return function(_, ...)
                return sock[n](sock, ...)
            end
        end
    })
end

-- 统一请求函数
local function request(url)
    local res = {}
    local _, code, headers = https.request{
        url = url,
        sink = ltn12.sink.table(res),
        create = create,
        headers = {
            ['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
            ['Accept'] = 'text/calendar,*/*'
        },
        redirect = true -- 自动跟随重定向,默认开启可省略
    }
    return table.concat(res), code, headers
end

print("Fixtur.es Football (URL A) returns the following?")
local responseBodya, responseCodea, responseHeadersa = request(calendarUria)
print(responseCodea, #responseBodya)

print("Google UK Holidays (URL B) returns the following?")
local responseBodyb, responseCodeb, responseHeadersb = request(calendarUrib)
print(responseCodeb, #responseBodyb)

如果需要开启证书校验避免中间人攻击,只需要在ssl.wrap的配置中添加cafile = "你的根证书路径",并将verify改为'peer'即可。

内容的提问来源于stack exchange,提问作者nodecentral

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:54:03