2016-05-17 204 views
2

爲了開發目的,並不是每個人都可以在他們的機器上安裝nginx(就像我們在Windows環境下的開發人員一樣),但我們希望能夠做一個像nginx一樣的反向代理。實現一個像nginx一樣的Undertow反向代理

這是我們非常具體的情況:

運行春季啓動Web應用程序的彈簧引導REST服務,我們願竭誠爲兩服務http://0.0.0.0:8080

所以我們想這樣映射它:

它像nginx的用URL重寫反向代理的方式。

我查看了Undertow源代碼和示例,甚至還有這個具體示例:Reverse Proxy Example,但這是一個負載平衡器示例,我還沒有找到任何涵蓋我需要的示例。

另外,我知道Undertow能夠做到這一點,因爲我們知道我們可以通過Undertow組件配置來配置WildFly來覆蓋這個特定的案例,但沒有問題,但我們希望自己實現它作爲本地開發的輕量級解決方案。

有沒有人知道這樣做的一個例子?或有足夠的信息來實現這一點的任何文檔?因爲我也閱讀了Undertow有關反向代理的文檔,它根本沒有幫助。

感謝

+1

爲什麼不簡單地使用Zuul代理來做到這一點。另外Windows用戶完全可以[運行nginx](http://nginx.org/en/docs/windows.html)。多次使用(用於測試目的)並像魅力一樣工作。 –

+0

聽起來沒問題,但我們希望將此作爲學習體驗,而且,如果我們將此反向代理添加爲Gradle項目中的模塊,則開發人員不必在其計算機上配置任何內容,因爲代理將被包含在那裏。 –

+1

他們仍然必須啓動它,並且您始終可以創建一個gradle taks,下載,解壓縮,配置nginx代理。或者使用虛擬機和/或碼頭工具。但是,因爲您已經使用Spring Boot,添加Zuul代理應該非常容易。 –

回答

0

按M. Deinum的意見建議,我會使用,而不是試圖與暗潮做到這一點Zuul春天引導組件,因爲它更適合這個任務。

這裏有一個教程的鏈接做到這一點:

https://spring.io/guides/gs/routing-and-filtering/

希望這有助於任何人,因爲這是一個很常見的情況,我不知道Zuul在春季啓動。

0

這應該做的工作。

它是Java8所以有些部分可能無法在您的設置上工作。

您可以使用與您在問題中提到的the example類似的方式啓動它。

package com.company 

import com.google.common.collect.ImmutableMap; 
import io.undertow.client.ClientCallback; 
import io.undertow.client.ClientConnection; 
import io.undertow.client.UndertowClient; 
import io.undertow.server.HttpServerExchange; 
import io.undertow.server.ServerConnection; 
import io.undertow.server.handlers.proxy.ProxyCallback; 
import io.undertow.server.handlers.proxy.ProxyClient; 
import io.undertow.server.handlers.proxy.ProxyConnection; 
import org.xnio.IoUtils; 
import org.xnio.OptionMap; 

import java.io.IOException; 
import java.net.URI; 
import java.util.concurrent.TimeUnit; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

/** 
* Start the ReverseProxy with an ImmutableMap of matching endpoints and a default 
* 
* Example: 
* mapping: ImmutableMap("api" -> "http://some-domain.com") 
* default: "http://default-domain.com" 
* 
* Request 1: localhost:8080/foo -> http://default-domain.com/foo 
* Request 2: localhost:8080/api/bar -> http://some-domain.com/bar 
*/ 

public class ReverseProxyClient implements ProxyClient { 
    private static final ProxyTarget TARGET = new ProxyTarget() {}; 

    private final UndertowClient client; 
    private final ImmutableMap<String, URI> mapping; 
    private final URI defaultTarget; 

    public ReverseProxyClient(ImmutableMap<String, URI> mapping, URI defaultTarget) { 
     this.client = UndertowClient.getInstance(); 
     this.mapping = mapping; 
     this.defaultTarget = defaultTarget; 
    } 

    @Override 
    public ProxyTarget findTarget(HttpServerExchange exchange) { 
     return TARGET; 
    } 

    @Override 
    public void getConnection(ProxyTarget target, HttpServerExchange exchange, ProxyCallback<ProxyConnection> callback, long timeout, TimeUnit timeUnit) { 
     URI targetUri = defaultTarget; 

     Matcher matcher = Pattern.compile("^/(\\w+)(/.*)").matcher(exchange.getRequestURI()); 
     if (matcher.find()) { 
      String firstUriSegment = matcher.group(1); 
      String remaininguri = matcher.group(2); 
      if (mapping.containsKey(firstUriSegment)) { 
       // If the first uri segment is in the mapping, update the targetUri 
       targetUri = mapping.get(firstUriSegment); 
       // Strip the request uri from the part that is used to map upon. 
       exchange.setRequestURI(remaininguri); 
      } 
     } 

     client.connect(
      new ConnectNotifier(callback, exchange), 
      targetUri, 
      exchange.getIoThread(), 
      exchange.getConnection().getByteBufferPool(), 
      OptionMap.EMPTY); 
    } 

    private final class ConnectNotifier implements ClientCallback<ClientConnection> { 
     private final ProxyCallback<ProxyConnection> callback; 
     private final HttpServerExchange exchange; 

     private ConnectNotifier(ProxyCallback<ProxyConnection> callback, HttpServerExchange exchange) { 
      this.callback = callback; 
      this.exchange = exchange; 
     } 

     @Override 
     public void completed(final ClientConnection connection) { 
      final ServerConnection serverConnection = exchange.getConnection(); 
      serverConnection.addCloseListener(serverConnection1 -> IoUtils.safeClose(connection)); 
      callback.completed(exchange, new ProxyConnection(connection, "/")); 
     } 

     @Override 
     public void failed(IOException e) { 
      callback.failed(exchange); 
     } 
    } 
}