如何在Jsoup捕获HttpStatusException时获取Retry-After响应头?
解决Jsoup 429状态下获取Retry-After响应头的问题
核心思路:忽略HTTP错误码,直接获取响应对象
默认情况下,Jsoup遇到4xx/5xx状态码会抛出HttpStatusException,导致无法拿到响应头。通过ignoreHttpErrors(true)配置,可让Jsoup不抛出异常,直接返回包含错误状态的Connection.Response,从而正常读取响应头。
修改后的代码示例
Connection.Response response = Jsoup.connect(urlstr) .ignoreHttpErrors(true) // 关键设置:不抛出HTTP错误异常 .execute(); int statusCode = response.statusCode(); if (statusCode == 200) { // 请求成功,处理响应内容 } else if (statusCode == 429) { // 获取Retry-After头 String retryAfter = response.headers().get("Retry-After"); if (retryAfter != null) { // 解析延迟时长(支持秒数或HTTP日期格式) try { long delaySeconds = Long.parseLong(retryAfter); Thread.sleep(delaySeconds * 1000); } catch (NumberFormatException e) { // 日期格式解析失败时用默认延迟 Thread.sleep(60 * 1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } else { // 处理其他错误状态码 }
补充说明
ignoreHttpErrors(true)会让Jsoup返回所有状态码的响应,需自行判断状态码区分成功/失败场景。- Retry-After头有两种格式:秒数字符串(如
120)或HTTP日期字符串(如Fri, 01 Jan 2025 12:00:00 GMT),需根据实际情况解析。 - 若必须保留原异常捕获逻辑,可通过反射访问
HttpStatusException内部的response字段(不推荐,依赖内部实现易失效):
catch (final HttpStatusException e) { if (e.getStatusCode() == 429) { try { Field responseField = HttpStatusException.class.getDeclaredField("response"); responseField.setAccessible(true); Connection.Response errorResponse = (Connection.Response) responseField.get(e); String retryAfter = errorResponse.headers().get("Retry-After"); // 处理延迟逻辑 } catch (NoSuchFieldException | IllegalAccessException ex) { // 反射失败时的降级处理 } } }
内容的提问来源于stack exchange,提问作者JonB
相关产品推荐
相关产品推荐

