Error 403 forbidden when consuming webservice CEP

2

I'm trying to consume a webservice from ceps but it always returns me 403 and it's public.

WebService Test Running:

link

My Controller

@Controller
@RequestMapping("/busca-cep")
public class BuscaCEPController {

    private static final Logger LOG = LoggerFactory.getLogger(BuscaCEPController.class);

    @Autowired
    private LogService logService;

    @Autowired
    private BuscaCEPService buscaCEPService;

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<CEPResult> buscaCEP(String code) {
        try {
            logService.info(LOG, "action=buscaCEPIniciado, cep={}", code);
            CEPResult result = buscaCEPService.buscarCEP(code); 
            logService.info(LOG, "action=buscaCEPConcluido, cep={}", code);
            return new ResponseEntity<CEPResult>(result, HttpStatus.OK);
        } catch (Exception e) {
            logService.error(LOG, "action=buscaCEPErro, cep={}, e={}", code, e.getMessage());
            return new ResponseEntity<CEPResult>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

}

My Consumer Service

  @Service
    public class BuscaCEPService {

        public CEPResult buscarCEP(String code) {
            RestTemplate restTemplate = new RestTemplate();
            CEPResult result = restTemplate.getForObject("http://apps.widenet.com.br/busca-cep/api/cep.json?code=" + code, CEPResult.class);
            return result;
        }

    }
    
asked by anonymous 16.11.2015 / 17:09

1 answer

3

I tested calls to this sample URL provided:

http://apps.widenet.com.br/busca-cep/api/cep.json?code=01001000

What I noticed and what causes 403 is that the server needs the User-Agent header to be present in the request, regardless of header content, and may be empty.

So what we need to do is put this header so that the request will go with it.

With getForObject of RestTemplate there is no way to report headers, an alternative is to run exchange passing a HttpEntity to the required headers.

An example demonstrated this approach would look like this:

private static final String URL = "http://apps.widenet.com.br/busca-cep/api/cep.json?code={code}";

public String findCEPByCode(final String code) {
    final RestTemplate template = new RestTemplate();

    final HttpHeaders headers = new HttpHeaders();
    headers.set(HttpHeaders.USER_AGENT, "");

    final HttpEntity<?> entity = new HttpEntity<>(headers);

    final ResponseEntity<String> result = template.exchange(URL, HttpMethod.GET, entity, String.class, code);

    return result.getBody();
}

public static void main(final String[] args) {
    System.out.println(new CEPService().findCEPByCode("01001000"));
}

That will generate this JSON (in unicode why did not force anything for UTF-8):

{
   "status":1,
   "code":"01001-000",
   "state":"SP",
   "city":"S\u00e3o Paulo",
   "district":"S\u00e9",
   "address":"Pra\u00e7a da S\u00e9 - lado \u00edmpar"
}

To return your CEPResponse , simply change the type, thus:

public CEPResponse findCEPByCode(final String code) {
    final RestTemplate template = new RestTemplate();

    // dependendo das configurações do contexto do spring não precisará disto
    template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

    final HttpHeaders headers = new HttpHeaders();
    headers.set(HttpHeaders.USER_AGENT, "");

    final HttpEntity<?> entity = new HttpEntity<>(headers);

    final ResponseEntity<CEPResponse> result = template.exchange(URL, HttpMethod.GET, entity, CEPResponse.class, code);

    return result.getBody();
}
    
17.11.2015 / 03:01