Spring Openfeign 잘 요청했는데 왜 401?

업데이트:

개요

Netflix Openfeign 라이브러리를 이용해 elasticsearch와 http 통신하고자 했다. elasticsearch에는 id/pw 기반 인증이 있어서 http://{id}:{pw}@{es-endpoint} 형식의 http basic auth로 요청했는데 401이 돌아오더라.

이유

OpenFeign이 http://{id}:{pw}@{domain}과 같이 url에 id/pw가 포함된 요청을 잘 처리하지 못한다. 기본적으로 http basic auth는, Authorization 헤더에 {id}:{pw}를 base64 인코딩한 값을 포함하도록 되어있다.

크롬, 사파리와 같은 현대의 웹 에이전트들은 http://{id}:{pw}@{domain} 와 같은 요청이 들어오면 base64로 인코딩하고 Authorization 헤더로 변환하는 일련의 과정을 수행해주는데, 아쉽게도 OpenFeign에서는 제공하지 않는 것 같아보인다.

해결

우선 id:pw여기서 base64 인코딩했다.
그 후, ElasticSearch OpenFeign Client가 항상 Authorization을 포함하도록 Config를 작성했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// EsFeignConfig.java
package com.a.b.c.httpclient.elasticsearch;

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

public class EsFeignConfig {
    @Value("${internal-service.elasticsearch.authorization}")
    private String authorization;

    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            requestTemplate.header("Content-Type", "application/json");
            requestTemplate.header("Authorization", "Basic " + authorization);
        };
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// EsClient.java
package com.a.b.c.httpclient.elasticsearch;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;


@FeignClient(name="es-client", url="${internal-service.elasticsearch.url}", configuration = EsFeignConfig.class)
public interface EsClient {
    @PostMapping(value="/events_v1/_doc/{eventId}")
    void upsertEvent(@PathVariable("eventId") Long eventId, @RequestBody EsDto.EventRequest body);
}

댓글남기기