Spring - Feign client

choko's avatar
Jun 29, 2024
Spring - Feign client
 
 

Feign

 
  • 스프링 환경에서 간편하게 외부 api를 호출할 수 있는 라이브러리
  • build.gradle(Spring boot 3.2 기준 spring-cloud-dependencies:2023.0.0, openfeign:4.1.0)
repositories { mavenCentral() } dependencies( implementation 'org.springframework.cloud:spring-cloud-starter-config' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation("org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0") ) dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:2023.0.0" } }
 
  • 사용법
    • https://api.github.com/repos/{owner}/{feign}/contributors 에 GET 요청을 보내는 예시
      1. @EnableFeignClients 어노테이션
      @SpringBootApplication() @EnableFeignClients @PropertySource("classpath:/application.properties") public class StudyApplication { public static void main(String[] args) { SpringApplication.run(StudyApplication.class, args); } }
       
      1. @FeignClient 인터페이스 등록
      @FeignClient(name = "feign", url = "https://api.github.com/repos") public interface GithubFeignClient { @RequestMapping(method = RequestMethod.GET, value="/{owner}/{repo}/contributors") List<Contributor> getContributors(@PathVariable("owner") String owner, @PathVariable("repo") String repo); }
    • url 뒤에 @RequestMapping , @PathVariable , @RequestParam 등으로 url 매핑
    •  
      1. 서비스에서 인터페이스 호출 → Entity를 생성하여 컨트롤러에 전달해준다.
      @RequiredArgsConstructor @Service @Slf4j public class GithubFeignService { private final GithubFeignClient githubFeignClient; public List<Contributor> getContributors(String owner, String repo) { List<Contributor> contributors = githubFeignClient.getContributors(owner, repo); for (Contributor c : contributors) { //log.info("id: {}", c.getId()); } log.info("!! contributors !! : {}", contributors); return contributors; } }
       
       
 
 
 
 

Trouble Shooting

  • feign으로 응답 가져올 시 302 Not Found 에러
@FeignClient(name = "test", url = "http://t-data.seoul.go.kr/apig/apiman-gateway/tapi/v2xSignalPhaseTimingInformation/1.0") public interface LightFeign { @RequestMapping(method = RequestMethod.GET) public List<LightResponse> call(@RequestParam("apiKey") String apiKey, @RequestParam("itstId") String itstId, @RequestParam("pageNo") String pageNo, @RequestParam("numOfRows") String numOfRows); } feign.FeignException: [302 Found] during [GET] to [http://t-data.seoul.go.kr/apig/apiman-gateway/tapi/v2xSignalPhaseTimingInformation/1.0?apiKey=b2a72569-9548-4d0d-bd01-8fca5d2740df&itstId=22904&pageNo=1&numOfRows=1] [LightFeign#call(String,String,String,String)]: [<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <HTML><HEAD> <TITLE> 302 Found </TITLE> </HEAD><BODY> <H1>Found</H1> <HR> </BODY></HTML> ]] with root cause
  • Http 302 Found
    • 일단, 302 Found는 정상적으로 응답 데이터를 받아왔다는 의미이다.
    • 클라이언트가 임시적으로 리다이렉션을 발생시킨 것이다.
  • 왜 리다이렉션이 일어났나?
    • 요청을 https가 아닌 http로 보냈는데, t-data.seoul.go.kr 에서 http로 요청이 오면 https로 자동 리다이렉션이 되도록 해놨기 때문이다.
    • http 요청 → 302 Found, https로 리다이렉션
      • notion image
    • https 요청 → 200 ok
notion image
 
  • 해결
      1. 요청 url을 http에서 https로 변경한다.
      1. 인증서 에러 발생할 경우 - https://velog.io/@dev_yong/PKIX-path-building-failed
      https Error - PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException
      → 해당 사이트의 인증서가 JVM이 신뢰하는 인증서 목록에 없어서 발생함
      • 위 블로그를 참고하여 InstallCert 를 통해 해당 사이트의 인증서를 jvm keystore에 등록한다.
      • 등록 후 서버 재시작하면 문제가 해결된다.
  1. javac InstallCert.java
  1. java -cp ./ InstallCert t-data.seoul.go.kr
  1. Added certificate to keystore 'jssecacerts' using alias 't-data.seoul.go.kr'
  1. sudo keytool -importcert -keystore ${JAVA_HOME}/lib/security/cacerts -storepass changeit -file output.cert -alias letsencrypt
 
 
 

ref
Share article

Tom의 TIL 정리방