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

Spring Boot中RestTemplate调用API遇403 Forbidden(error code:1010)求助

Spring Boot RestTemplate调用API时403 Forbidden(错误码1010)问题解决

问题描述

使用Spring Boot的RestTemplate调用RapidAPI上的新冠数据接口时,持续收到403 Forbidden错误,错误码为1010。

相关代码

Country.java(响应实体类)

@NoArgsConstructor
@Getter
public class Country {
    private String name;

    private double iso_code;

    @Override
    public String toString() {
        return "Name: " + name + "\nIso Code: " + iso_code;
    }
}

CountryRestClient.java(API调用客户端)

@Component
public class CountryRestClient {

    private static final String url = "https://vaccovid-coronavirus-vaccine-and-treatment-tracker.p.rapidapi.com/api/npm-covid-data/countries-name-ordered";


    private static final String apiKeyName = "X-RapidAPI-Key";

    private static final String apiKeyValue = "42f0727d22msh9d";

    private static final String hostName = "X-RapidAPI-Host";

    private static final String hostValue = "vaccovid-coronavirus-vaccine-and-treatment-tracker.p.rapidapi.com";

    RestTemplate restTemplate;

    public CountryRestClient(RestTemplateBuilder restTemplateBuilder) {
        restTemplate = restTemplateBuilder.build();
    }


    public Country getCountry() {
        Country country = null;
        try {
            URI uri = new URI(url);

            HttpHeaders headers = new HttpHeaders();
            headers.set(apiKeyName, apiKeyValue);
            headers.set(hostName, hostValue);

            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

            HttpEntity<String> request = new HttpEntity<>(headers);

            ResponseEntity<Country[]> countryEntity = restTemplate.exchange(uri, HttpMethod.GET, request, Country[].class);

            country = countryEntity.getBody()[0];

            System.out.println("Name:" + country.getName() + "\nISO: " + country.getIso_code());

        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return country;
    }
}

CountryController.java(接口暴露层)

@RestController
public class CountryController {

    @GetMapping("/countries")
    public Country getCountries() {
        return new CountryRestClient(new RestTemplateBuilder()).getCountry();
    }

}

错误栈信息

**Whitelabel Error Page**
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Sep 08 23:10:25 EDT 2022
There was an unexpected error (type=Internal Server Error, status=500).
403 Forbidden: "error code: 1010"
org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden: "error code: 1010"
    at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:109)
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:168)
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:122)
    at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:819)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:777)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:751)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:621)
    at com.thymeleafdemo.client.CountryRestClient.getCountries(CountryRestClient.java:49)
    at com.thymeleafdemo.controller.CountryController.getCountries(CountryController.java:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1070)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:750)

排查与解决步骤

1. 检查API Key的有效性与完整性

  • 当前使用的apiKeyValue是截断状态(42f0727d22msh9d),RapidAPI的合法Key长度更长,需登录RapidAPI账号进入对应API的控制台,复制完整的API Key替换现有值。
  • 确认API Key未过期,且账号在目标API上有剩余调用配额(免费版存在调用次数限制)。

2. 清理不必要的请求头

  • GET请求无需设置Content-Type头(无请求体),移除headers.setContentType(MediaType.APPLICATION_JSON);这一行,避免冗余头信息干扰接口验证。

3. 修正实体类字段类型

  • 接口返回的iso_code是字符串格式(如"US"、"CN"),但当前Country类中定义为double,会导致反序列化失败。将private double iso_code;修改为private String iso_code;。

4. 修复Spring依赖注入逻辑

  • CountryRestClient已标注@Component,但CountryController中直接实例化对象,未使用Spring容器管理的实例,不符合最佳实践。改为构造方法注入:
@RestController
public class CountryController {

    private final CountryRestClient countryRestClient;

    public CountryController(CountryRestClient countryRestClient) {
        this.countryRestClient = countryRestClient;
    }

    @GetMapping("/countries")
    public Country getCountries() {
        return countryRestClient.getCountry();
    }
}

5. 添加错误详情日志

  • 给RestTemplate添加自定义错误处理器,便于查看API返回的完整错误信息:
public CountryRestClient(RestTemplateBuilder restTemplateBuilder) {
    restTemplate = restTemplateBuilder
            .errorHandler(new DefaultResponseErrorHandler() {
                @Override
                public void handleError(ClientHttpResponse response) throws IOException {
                    String responseBody = new String(response.getBody().readAllBytes(), StandardCharsets.UTF_8);
                    System.err.println("API错误响应:" + responseBody);
                    super.handleError(response);
                }
            })
            .build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:54:22