13

我想从主机为在 VM 中运行的两个或多个 Web 应用程序提供服务(不同的端口,有时在同一端口下的不同目录中),因为我需要先登录用户才能访问那些我无法使用的应用程序像 Nginx 或 Apache 这样的静态代理。

所以这是我的情况:

192.168.1.1 : 是主机 ip
192.168.1.2 : 是虚拟机 ip

在VM里面我有这个:

192.168.1.2/owncloud:owncloud 地址
192.168.1.2:8080:另一个应用程序
192.168.1.2:8888:第三个应用程序

我想要这个:

192.168.1.1/app1 --> 192.168.1.2/owncloud
192.168.1.1/app2 --> 192.168.1.2:8080
192.168.1.1/app2 --> 192.168.1.2:8888

我曾尝试使用 golang httputil.ReverseProxy 来实现此路由,但没有多大成功:我的代码基于这项工作:gist

package main

import(
    "log"
    "net/url"
    "net/http"
    "net/http/httputil"
)

func main() {
    remote, err := url.Parse("http://192.168.1.2:8080")
    if err != nil {
            panic(err)
    }

    proxy := httputil.NewSingleHostReverseProxy(remote)
    http.HandleFunc("/app2", handler(proxy))
    err = http.ListenAndServe(":80", nil)
    if err != nil {
            panic(err)
    }
}

func handler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        log.Println(r.URL)
        r.URL.Path = "/"                
            p.ServeHTTP(w, r)
    }
}

编辑:
我更改了 vm ip 地址:192.168.1.2 而不是 192.168.1.1

4

3 回答 3

6

制作这样的地图

hostTarget = map[string]string{
    "app1.domain.com": "http://192.168.1.2/owncloud",
    "app2.domain.com": "http://192.168.1.2:8080",
    "app3.domain.com": "http://192.168.1.2:8888",
}

使用httputil.ReverseProxy构建你的处理程序

type baseHandle struct{}

func (h *baseHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    host := r.Host

    if target, ok := hostTarget[host]; ok {
        remoteUrl, err := url.Parse(target)
        if err != nil {
            log.Println("target parse fail:", err)
            return
        }

        proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
        proxy.ServeHTTP(w, r)
        return
    }
    w.Write([]byte("403: Host forbidden " + host))
}

聆听并服务

h := &baseHandle{}
http.Handle("/", h)

server := &http.Server{
    Addr:    ":8080",
    Handler: h,
}
log.Fatal(server.ListenAndServe())

您可以缓存httputil.ReverseProxy在全局地图中,全部在上面的文件中

这是一个与您最匹配的SSLDocker项目。

于 2017-12-03T04:06:29.737 回答
4

您最好通过主机名而不是 URL 来执行此操作。例如

owncloud.domain.com -> IP 192.168.1.2,
app2.domain.com     -> IP 192.168.1.3

如果您还不知道,主机名只是一个 HTTP 请求标头(主机:domain.com),因此每个 IP 可以有多个主机名(Apache 称之为“命名虚拟主机”)。

使用主机名而不是 URL 的好处是,另一端的 Web 应用程序不知道您添加前缀的 URL,但需要尊重它们,因此您可能会遇到由 Web 应用程序编写的 URL 的问题,而不是处理反向代理所期望的 URL。基于主机名的代理应该可以工作,因为大多数网络应用程序不会重写域名。(虽然这是一个很大的概括,但一些 Web 应用程序将允许您添加代理地址 - 但通常您会遇到较少的主机名问题)

最大的问题是必须在您的名称服务器上设置子域。我假设您的注册/DNS 提供商允许您免费创建子域(大多数应该),但是如果您使用动态 DNS 之类的东西,而这会影响您的家庭宽带连接,那么您会遇到问题并且会有购买您自己的域名,并将子域 CNAME'ed 到您的动态 DNS 地址(或使用您的动态 DNS 提供商的付费帐户,如果他们提供子域)。

最后一件事,如果您正在研究 owncloud,那么您可能还想看看 Pydio(以前称为 AjaxExplore)。它们都有不同的优点和缺点,但在我个人看来,Pydio 是一个更好的产品。

于 2014-01-18T17:00:40.450 回答
1

您将错误的 IP 传递给反向代理。应该是你的虚拟机的192.168.1.2.

文档中

NewSingleHostReverseProxy returns a new ReverseProxy that rewrites URLs to the scheme, host, and base path provided in target.

于 2014-01-13T11:38:46.653 回答