使用Spring RestTemplate调用weather.gov API遇403 Forbidden问题求助
使用Spring的RestTemplate调用weather.gov的API获取JSON数据,已添加User-Agent请求头,但仍返回403 Forbidden错误。
代码
@RequestMapping(value = "/api/v1/forecast", method = RequestMethod.GET) @ResponseBody public ResponseEntity<ReturnMessage> getForecast(@RequestParam Map<String, Object> params, ModelMap model) { final Logger LOGGER = LoggerFactory.getLogger(ForecastController.class); ReturnMessage message = new ReturnMessage(); RestTemplate restTemplate = new RestTemplate(); String url = "https://api.golde.gov"; System.out.println("loggg======="); LOGGER.info("link part " + url); HttpEntity<String> entity = new HttpEntity<String>(jsonObject.toString(), headers); String result = restTemplate.postForObject(url, entity, String.class); System.out.println(result); return ResponseEntity.ok(message); }
异常堆栈信息
org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden: "<HTML><HEAD><EOL><TITLE>Access Denied</TITLE><EOL></HEAD><BODY><EOL><H1>Access Denied</H1><EOL> <EOL>You don't have permission to access "http://api.weather.gov/gridpoints/OKX/33,35/forecast" on this server.<P><EOL>Reference #18.177c2117.1685609346.4b1d971<EOL></BODY><EOL></HTML><EOL>" at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:109) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:183) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:137) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:915) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:864) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:764) ~[spring-web-6.0.9.jar:6.0.9] at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:481) ~[spring-web-6.0.9.jar:6.0.9] at com.forecast.veriserve.controller.ForecastController.getForecast(ForecastController.java:105) ~[classes/:na]
针对你的问题,结合代码和weather.gov的API规则,需要修复以下几个关键点:
修正API地址:代码中
url拼写错误,正确地址应为https://api.weather.gov,结合异常信息里的目标接口,完整URL是https://api.weather.gov/gridpoints/OKX/33,35/forecast。使用正确的请求方法:weather.gov的预报接口为GET请求,你当前用
postForObject()发送POST请求,不符合接口要求,应改用exchange()或getForObject()发送GET请求。完善请求头配置:weather.gov要求
User-Agent必须包含联系方式(如邮箱),同时建议指定Accept头明确接收JSON格式数据,示例配置:HttpHeaders headers = new HttpHeaders(); headers.set("User-Agent", "你的应用名称/版本 (你的联系邮箱)"); headers.set("Accept", "application/geo+json");配置RestTemplate处理重定向:部分weather.gov接口会返回3xx重定向,默认RestTemplate可能无法正确处理,可通过引入Apache HttpClient来配置自动重定向:
RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());需添加依赖:
org.apache.httpcomponents:httpclient移除不必要的请求体:当前接口为GET请求,不需要请求体,应构造无请求体的
HttpEntity:new HttpEntity<>(headers)
修正后的示例代码:
@RequestMapping(value = "/api/v1/forecast", method = RequestMethod.GET) @ResponseBody public ResponseEntity<ReturnMessage> getForecast(@RequestParam Map<String, Object> params, ModelMap model) { final Logger LOGGER = LoggerFactory.getLogger(ForecastController.class); ReturnMessage message = new ReturnMessage(); // 配置支持重定向的RestTemplate RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); // 正确的API请求地址 String url = "https://api.weather.gov/gridpoints/OKX/33,35/forecast"; LOGGER.info("请求地址: " + url); // 配置符合要求的请求头 HttpHeaders headers = new HttpHeaders(); headers.set("User-Agent", "MyForecastApp/1.0 (myemail@example.com)"); headers.set("Accept", "application/geo+json"); HttpEntity<Void> entity = new HttpEntity<>(headers); // 发送GET请求并获取响应 String result = restTemplate.exchange(url, HttpMethod.GET, entity, String.class).getBody(); System.out.println(result); // 处理返回结果并封装到message中 // ... return ResponseEntity.ok(message); }
内容的提问来源于stack exchange,提问作者Khanh Luong Van

