티스토리 뷰

반응형

 

build.gradle 파일에 의존성을 넣어준다.

dependencyManagement {
	imports {
		mavenBom("org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR9")
	}
}

dependencies {
	implementation("org.springframework.cloud:spring-cloud-starter-openfeign")
	implementation("io.github.openfeign:feign-httpclient:11.0")
}

 

 

 

Applicaton.kt 에 @EnableFeignClients 어노테이션을 이용해

Feign 클라이언트 사용을 선언해준다.

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.cloud.openfeign.EnableFeignClients

@EnableFeignClients
@SpringBootApplication
class Application {
}

fun main(args: Array<String>) {
	runApplication<Application>(*args)
}

 

 

 

application.yml 파일에 외부 서버와의 통신에 필요한 프로퍼티 내용을 추가한다.

(PDNS 서버와의 통신을 위해 작업 중)

props:
  powerdns-service:
    url: http://localhost:9191/api/v1
    api-key: akh4TGJTTGVwTjS4ZXYy

 

 

 

외부와의 통신을 담당할 클라이언트 인터페이스를 만들어 준다.

import shop.janes.apis.client.pdns.dto.DnsGetResponse
import shop.janes.apis.config.PowerDnsConfig
import org.springframework.cloud.openfeign.FeignClient
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod

@FeignClient(name = "powerdns-service", url = "\${props.powerdns-service.url}", configuration = [PowerDnsConfig::class])
interface PowerDnsServiceClient {

	@RequestMapping(method = [RequestMethod.GET], value = ["/servers/localhost/zones/{zoneId}"])
	fun get(@PathVariable(name = "zoneId", required = true) zoneId: String): DnsGetResponse

}

이 때, @FeignClent 어노테이션을 이용해 설정해주는 것이 중요한데, url은 프로퍼티 값을 불러오도록 하고,

config 파일을 통해 통신을 할 때 Hearder에 필요한 구성 요소 및 로그 설정 등을 할 수 있다.

 

또한, 호출할 외부 REST API의 Request Method와 uri 값을 잘 작성해주어야 하는데,

uri에는 기존 컨트롤러와 동일하게 설정해주면 된다.

uri에 따라 @PathVariable, @RequestBody 등의 어노테이션을 이용할 수 있다.

 

마지막으로 응답을 받을 때는 응답이 오는 구조와 동일하게

데이터 클래스를 작성하여 Reponse를 매핑해올 수 있다.

(필요한 결과만 매핑도 가능)

 

 

 

먼저, config 파일에는 Hearder에 API 통신을 위한 키 값을 설정해주었고,

Feign 클라이언트의 통신 로그를 자세히 보기 위해 로그 레벨도 설정해주었다.

import feign.Logger
import feign.RequestInterceptor
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class PowerDnsConfig {

    @Bean
    fun feignLoggerLevel(): Logger.Level? {
        return Logger.Level.FULL
    }

    @Bean
    fun requestInterceptor(@Value("\${props.powerdns-service.api-key}") key: String) : RequestInterceptor {
        return RequestInterceptor {
            it.header("X-API-Key", key)
        }
    }

}

 

 

 

아래는 응답을 받아올 데이터 모델이다.

data class DnsGetResponse(

	val id: String,

	val name: String,

	val dnssec: Boolean,

	val rrsets: List<Record>,

	val serial: Long

)
data class Record(

	var name: String?,

	val type: Type?,

	val ttl: Int?,

	val records: List<Map<String, Any>>?,

	val comments: List<Map<String, Any>>?

) {

	enum class Type {
		A, AAAA, ALIAS, CAA, CNAME, DNAME, LOC, LUA, MX, NS, PTR, RRSIG, SOA, SPF, SRV, TXT
	}

}

 

 

 

여기서 문제가 있는데, 응답에 성공을 했을 땐 제대로 값을 받아오는데,

실패 했을 때는 실패 응답 errorMessage 값만은 못 담아왔다.

(이 문제는 해결되면 다시 포스팅 예정)

 

 

 

 

 

이제 외부 통신과 연결을 했으니 컨트롤러와 서비스를 작성한다.

import shop.janes.apis.client.pdns.dto.DnsGetResponse
import shop.janes.apis.web.v1.domain.record.service.RecordService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/records/{domain}", "/v1/records/{domain}")
class RecordController(
	private val recordService: RecordService
) {

	@GetMapping()
	fun listRecords(@PathVariable domain: String): ResponseEntity<DnsGetResponse> {
		return ResponseEntity.ok(recordService.listRecords(domain))
	}

}
import shop.janes.apis.client.pdns.PowerDnsServiceClient
import shop.janes.apis.client.pdns.dto.DnsGetResponse
import org.springframework.stereotype.Service

@Service
class RecordService(
	private val powerDnsServiceClient: PowerDnsServiceClient
) {
	
	fun listRecords(domain: String): DnsGetResponse {
		return powerDnsServiceClient.get(domain)
	}

}

 

 

 

 

 

API를 호출하면 아래와 같이 @FeignClient 를 이용해

연결한 외부 서버의 API 호출 값을 그대로 받아올 수 있다.

{
    "id": "janes.shop.",
    "name": "janes.shop.",
    "dnssec": false,
    "rrsets": [
        {
            "name": "www.janes.shop.",
            "type": "CNAME",
            "ttl": 60,
            "records": [
                {
                    "content": ".",
                    "disabled": false
                }
            ],
            "comments": []
        }
    ],
    "serial": 2022010402
}

아래처럼 위에서 config 파일에 설정했던 외부 통신 시 찍힌 로그들을 자세히 볼 수 있다.

2022-01-04 15:48:11.162 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] ---> GET http://localhost:9191/api/v1/servers/localhost/zones/janes.shop HTTP/1.1
2022-01-04 15:48:11.162 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] X-API-Key: akh4TGJTTGVwTjS4ZXYy
2022-01-04 15:48:11.162 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] ---> END HTTP (0-byte body)
2022-01-04 15:48:11.877 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] <--- HTTP/1.1 200 OK (715ms)
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] access-control-allow-origin: *
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] connection: close
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] content-length: 738
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] content-security-policy: default-src 'self'; style-src 'self' 'unsafe-inline'
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] content-type: application/json
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] date: Tue, 04 Jan 2022 06:48:12 GMT
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] server: PowerDNS/4.6.0-alpha1.508.master.g853e27067
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] x-content-type-options: nosniff
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] x-frame-options: deny
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] x-permitted-cross-domain-policies: none
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] x-xss-protection: 1; mode=block
2022-01-04 15:48:11.878 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] 
2022-01-04 15:48:11.881 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] {"account": "", "api_rectify": false, "dnssec": false, "edited_serial": 2022010402, "id": "janes.shop.", "kind": "Native", "last_check": 0, "master_tsig_key_ids": [], "masters": [], "name": "janes.shop.", "notified_serial": 0, "nsec3narrow": false, "nsec3param": "", "rrsets": [{"comments": [], "name": "www.janes.shop.", "records": [{"content": ".", "disabled": false}], "ttl": 60, "type": "CNAME"}], "serial": 2022010402, "slave_tsig_key_ids": [], "soa_edit": "", "soa_edit_api": "DEFAULT", "url": "/api/v1/servers/localhost/zones/janes.shop."}
2022-01-04 15:48:11.881 DEBUG 34604 --- [  XNIO-1 task-1] k.h.a.client.pdns.PowerDnsServiceClient  : [PowerDnsServiceClient#get] <--- END HTTP (738-byte body)

(참고 : https://velog.io/@skyepodium/2019-10-06-1410-%EC%9E%91%EC%84%B1%EB%90%A8, https://techblog.woowahan.com/2630/)

 

 

 

 

 

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함