Micronaut 使用 ProxyHttpClient 代理請求

2023-03-08 14:35 更新

微服務(wù)環(huán)境中的一個(gè)常見需求是將網(wǎng)關(guān)微服務(wù)中的請求代理到其他后端微服務(wù)。

常規(guī)的 HttpClient API 是圍繞簡化消息交換而設(shè)計(jì)的,而不是為代理請求而設(shè)計(jì)的。對于這種情況,請使用 ProxyHttpClient,它可用于從 HTTP 服務(wù)器過濾器到后端微服務(wù)的代理請求。

以下示例演示了將 URI /proxy 下的請求重寫到同一服務(wù)器上的 URI /real(盡管在真實(shí)環(huán)境中您通常代理到另一臺服務(wù)器):

重寫原始請求的代理過濾器

 Java Groovy  Kotlin 
import io.micronaut.core.async.publisher.Publishers;
import io.micronaut.core.util.StringUtils;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MutableHttpResponse;
import io.micronaut.http.annotation.Filter;
import io.micronaut.http.client.ProxyHttpClient;
import io.micronaut.http.filter.HttpServerFilter;
import io.micronaut.http.filter.ServerFilterChain;
import io.micronaut.runtime.server.EmbeddedServer;
import org.reactivestreams.Publisher;

@Filter("/proxy/**")
public class ProxyFilter implements HttpServerFilter { // (1)

    private final ProxyHttpClient client;
    private final EmbeddedServer embeddedServer;

    public ProxyFilter(ProxyHttpClient client,
                       EmbeddedServer embeddedServer) { // (2)
        this.client = client;
        this.embeddedServer = embeddedServer;
    }

    @Override
    public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request,
                                                      ServerFilterChain chain) {
        return Publishers.map(client.proxy( // (3)
                request.mutate() // (4)
                        .uri(b -> b // (5)
                                .scheme("http")
                                .host(embeddedServer.getHost())
                                .port(embeddedServer.getPort())
                                .replacePath(StringUtils.prependUri(
                                        "/real",
                                        request.getPath().substring("/proxy".length())
                                ))
                        )
                        .header("X-My-Request-Header", "XXX") // (6)
        ), response -> response.header("X-My-Response-Header", "YYY"));
    }
}
import io.micronaut.core.async.publisher.Publishers
import io.micronaut.core.util.StringUtils
import io.micronaut.http.HttpRequest
import io.micronaut.http.MutableHttpResponse
import io.micronaut.http.annotation.Filter
import io.micronaut.http.client.ProxyHttpClient
import io.micronaut.http.filter.HttpServerFilter
import io.micronaut.http.filter.ServerFilterChain
import io.micronaut.http.uri.UriBuilder
import io.micronaut.runtime.server.EmbeddedServer
import org.reactivestreams.Publisher

@Filter("/proxy/**")
class ProxyFilter implements HttpServerFilter { // (1)

    private final ProxyHttpClient client
    private final EmbeddedServer embeddedServer

    ProxyFilter(ProxyHttpClient client,
                EmbeddedServer embeddedServer) { // (2)
        this.client = client
        this.embeddedServer = embeddedServer
    }

    @Override
    Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request,
                                               ServerFilterChain chain) {
        Publishers.map(client.proxy( // (3)
                request.mutate() // (4)
                        .uri { UriBuilder b -> // (5)
                            b.with {
                                scheme("http")
                                host(embeddedServer.host)
                                port(embeddedServer.port)
                                replacePath(StringUtils.prependUri(
                                        "/real",
                                        request.path.substring("/proxy".length())
                                ))
                            }
                        }
                        .header("X-My-Request-Header", "XXX") // (6)
        ), { it.header("X-My-Response-Header", "YYY") })
    }
}
import io.micronaut.core.async.publisher.Publishers
import io.micronaut.core.util.StringUtils
import io.micronaut.http.HttpRequest
import io.micronaut.http.MutableHttpResponse
import io.micronaut.http.annotation.Filter
import io.micronaut.http.client.ProxyHttpClient
import io.micronaut.http.filter.HttpServerFilter
import io.micronaut.http.filter.ServerFilterChain
import io.micronaut.http.uri.UriBuilder
import io.micronaut.runtime.server.EmbeddedServer
import org.reactivestreams.Publisher

@Filter("/proxy/**")
class ProxyFilter(
    private val client: ProxyHttpClient, // (2)
    private val embeddedServer: EmbeddedServer
) : HttpServerFilter { // (1)

    override fun doFilter(request: HttpRequest<*>,
                          chain: ServerFilterChain): Publisher<MutableHttpResponse<*>> {
        return Publishers.map(client.proxy( // (3)
            request.mutate() // (4)
                .uri { b: UriBuilder -> // (5)
                    b.apply {
                        scheme("http")
                        host(embeddedServer.host)
                        port(embeddedServer.port)
                        replacePath(StringUtils.prependUri(
                            "/real",
                            request.path.substring("/proxy".length))
                        )
                    }
                }
                .header("X-My-Request-Header", "XXX") // (6)
        ), { response: MutableHttpResponse<*> -> response.header("X-My-Response-Header", "YYY") })
    }
}
  1. 過濾器擴(kuò)展了 HttpServerFilter

  2. ProxyHttpClient 被注入到構(gòu)造函數(shù)中。

  3. 代理方法代理請求

  4. 請求發(fā)生變化以修改 URI 并包含一個(gè)額外的標(biāo)頭

  5. UriBuilder API 重寫 URI

  6. 包括額外的請求和響應(yīng)標(biāo)頭

ProxyHttpClient API 是一個(gè)低級 API,可用于構(gòu)建更高級別的抽象,例如 API 網(wǎng)關(guān)。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號