javaspringrestresttemplateweather-api

403 Forbidden: "<HTML><HEAD><EOL><TITLE>Access Denied</TITLE><EOL></HEAD><BODY><EOL><H1>You don't have permission to access


I'm using Spring and Rest Template to access and get data json

this is my code:

@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);
}

I have included a User-Agent header in my request but when i send to request to weather.gov to response an exception error:

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&#58;&#47;&#47;api&#46;weather&#46;gov&#47;gridpoints&#47;OKX&#47;33&#44;35&#47;forecast" on this server.<P><EOL>Reference&#32;&#35;18&#46;177c2117&#46;1685609346&#46;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]

How to fix the problem ? many thank


Solution

  • One problem could be:

    User-Agent: (myweatherapp.com, contact@myweatherapp.com)
    

    ..when reading the "Pricing" and "Authentication" sections.

    I could reproduce the issue immediately with HTTP POST! (-> 403), so don't use that (unless API changes).

    Here is the working mvc version with comments:

    // import java.util.*, org.spr..fr..*
    @RestController
    static class WeatherController {
        @Autowired
        RestTemplateBuilder rtplB;
    
        @GetMapping("/forecast")
        public Map getForecast() {
            // customize your api call(+response) from here:
            HttpHeaders headers = new HttpHeaders();
            headers.put("User-Agent",
                    List.of(UUID.randomUUID().toString(), // <- until API changes
                            "contact@my.funky.website.com")); // <- *your* contact, if you like
            headers.setAccept(List.of(MediaType.valueOf("application/geo+json")));
            HttpEntity<Void> ent = new HttpEntity<>(headers);
            return rtplB
                    .build()
                    .exchange(
                            "https://api.weather.gov/gridpoints/OKX/33,35/forecast", // customize, parametrize, call dynamically
                            HttpMethod.GET, // <- POST works not well (->403), didn't try the others..
                            ent, // <- request headers (+ body)
                            Map.class // response type
                            /* , uriVars/... */
                    ).getBody(); // <- returning ResponseEntity directly gave "strange" issues, "referencing" the body performs better (in browser).
        }
    }
    

    Here the webflux version:

    @Autowired
    WebClient.Builder wcB;
    
    @GetMapping("/forecast")
    public Mono<Map> getForecast(/*...*/) {
        return wcB.build()
                .get()
                .uri("https://api.weather.gov/gridpoints/OKX/33,35/forecast")
                .headers(
                    h -> {
                        h.put("User-Agent", List.of(UUID.randomUUID().toString(), "contact@my.funky.website.com"));
                        h.setAccept(List.of(MediaType.valueOf("application/geo+json")));
                    }
                )
                .retrieve().bodyToMono(Map.class);
    }
    

    BTW

    I had the "strange issues" (browser loading behavior) only on the mvc version, when directly returning resttemplate response, a "hold of the body" improves/fixes this. And a minimalist version:

    return rtplB.build()
     .getForObject(
       "https://api.weather.gov/gridpoints/OKX/33,35/forecast",
       Map.class
     ); // #
    

    ... "seems to work just fine".