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

使用http-client的call-with-input-request如何获取状态≥300的响应对象

调用call-with-input-request遇到非2xx状态码时获取响应对象的方法

call-with-input-request抛出的HTTP相关异常条件本身就绑定了完整的响应对象,不需要等待函数正常返回,通过Scheme原生的条件捕获机制即可取出,具体实现如下:

核心实现逻辑

  • 用CHICKEN内置的handle-exceptions语法包裹请求调用,捕获(exn http client-error)、(exn http server-error)、(exn http unexpected-server-response)三类HTTP异常。
  • 捕获到对应异常后,通过exn:http-response访问器直接从异常实例中提取响应对象,后续读取状态码、原因短语、响应头、响应体的操作和正常响应的处理逻辑完全一致。
  • 非HTTP类的异常不要捕获,直接重新抛出避免影响其他错误处理逻辑。

可直接运行的示例代码

(import http-client
        (chicken condition)
        (chicken port))

(handle-exceptions exn
  (cond
    ;; 匹配所有HTTP请求相关异常
    ((or (exn:http:client-error? exn)
         (exn:http:server-error? exn)
         (exn:http:unexpected-server-response? exn))
     (let* ((resp (exn:http-response exn)) ; 从异常中提取响应对象
            (status (http-response-status resp))
            (reason (http-response-reason resp))
            (body (read-string #f (http-response-port resp))))
       ;; 这里可以按需做日志打印、内容解析等操作
       (printf "请求返回非2xx状态,状态码:~a,原因:~a~n响应内容:~a~n"
               status reason body)))
    ;; 非HTTP异常直接向上抛出
    (else (abort exn)))
  ;; 正常请求逻辑
  (call-with-input-request "https://example.com/not-exist-path" #f
    (lambda (reader)
      (print "请求成功,响应内容:" (read-string #f reader)))))

补充说明

  • 不需要替换成其他底层请求函数,也不需要修改call-with-input-request的参数,异常携带响应是http-client库的默认实现,所有3xx-5xx区间的响应都可以通过这个方式拿到。
  • 从异常中取出的响应端口读取完成后会被GC自动回收,也可以手动调用close-input-port释放资源,避免端口占用。
  • 如果需要自行处理3xx跳转逻辑,可以在发起请求前将参数*follow-redirects?*设置为#f关闭自动跳转,此时3xx响应同样会以异常形式抛出,按上述方法提取响应即可。
  • 注意不要混淆不可继续异常的特性:不可继续仅代表异常触发后原函数不会恢复执行返回正常值,不代表异常对象本身携带的上下文数据会丢失,在异常捕获分支内可以正常访问所有绑定的字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:27:25