使用net/http的Sinatra客户端应用如何存储Cookie供后续请求使用
解决方案
针对无UI的Sinatra客户端应用存储上游服务session-id的需求,可根据部署场景选择以下两种实现方案:
方案1:单实例部署用全局内存存储(最简便)
如果你的Sinatra应用为单进程单实例部署,不需要额外引入中间件,直接用类变量存储session-id和对应过期时间即可:
# 放在Sinatra应用初始化部分,如config.ru或主应用文件开头 class UpstreamSessionManager @@session_id = nil @@expires_at = nil def self.get_valid_session # 存在未过期的session直接返回 return @@session_id if @@session_id && Time.now < @@expires_at # 过期或不存在时重新调用认证接口 uri = URI('https://上游服务地址/认证接口') res = Net::HTTP.post_form(uri, 'username' => '你的认证账号', 'password' => '你的认证密码') # 根据上游返回的Set-Cookie规则提取session-id,可根据实际响应调整提取逻辑 set_cookie = res['Set-Cookie'] @@session_id = set_cookie.match(/session-id=([^;]+)/)[1] # 提前1分钟过期,避免临界时间请求认证失败 @@expires_at = Time.now + 30 * 60 - 60 @@session_id end end
每次发起业务请求时,直接调用上述方法获取有效session注入Cookie头即可:
# 业务请求示例 uri = URI('https://上游服务地址/业务接口路径') req = Net::HTTP::Get.new(uri) # 注入有效session到请求头 req['Cookie'] = "session-id=#{UpstreamSessionManager.get_valid_session}" res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http| http.request(req) end
该方案仅适用于单进程单实例部署场景,多进程/多实例部署时会出现每个进程独立申请session的问题,无法共享session
方案2:多实例/多进程部署用分布式缓存
如果应用采用多实例部署,或者使用了Puma等多进程应用服务器,可引入Redis等分布式缓存存储session,保证所有实例共享同一个有效session:
# 应用初始化部分初始化Redis连接 require 'redis' $redis = Redis.new(host: '你的Redis服务地址', port: 6379) class UpstreamSessionManager SESSION_CACHE_KEY = 'upstream_service_session_id' def self.get_valid_session session_id = $redis.get(SESSION_CACHE_KEY) return session_id if session_id # 重新认证逻辑和方案1完全一致 uri = URI('https://上游服务地址/认证接口') res = Net::HTTP.post_form(uri, 'username' => '你的认证账号', 'password' => '你的认证密码') set_cookie = res['Set-Cookie'] session_id = set_cookie.match(/session-id=([^;]+)/)[1] # 写入Redis并设置29分钟过期时间,提前过期避免临界问题 $redis.setex(SESSION_CACHE_KEY, 29 * 60, session_id) session_id end end
业务请求的调用方式和方案1完全一致,不需要修改业务代码。
额外优化点
- 可以加锁避免并发场景下多个请求同时触发重新认证的问题,比如Redis分布式锁或者内存锁,避免上游收到大量重复认证请求
- 增加认证接口调用失败的重试和异常处理逻辑,避免单次认证失败导致所有业务请求报错
- 如果上游的session-id会在请求过程中动态刷新,每次收到业务请求的响应时需要检查
Set-Cookie头,及时更新存储的session-id和过期时间
内容的提问来源于stack exchange,提问作者Prayas Arora
相关产品推荐
相关产品推荐

