Golang обратный прокси с несколькими приложениями

Я хочу обслуживать два или более веб-приложений, работающих в виртуальной машине (разные порты и некоторое время в разных каталогах под одним и тем же портом) с хост-машины, и потому что мне нужно, чтобы пользователь вошел в систему, прежде чем он сможет получить доступ к этим приложениям, я не могу использовать статический прокси-сервер, такой как Nginx или Apache.

вот моя ситуация :

192.168.1.1 : есть IP хоста
192.168.1.2: является ли VM ip

внутри VM у меня есть это :

192.168.1.2 / owncloud: адрес owncloud
192.168.1.2: 8080: другое приложение
192.168.1.2:8888 : 3-е приложение

Я хочу иметь это:

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 для достижения этой маршрутизации, но без особого успеха: мой код на основе этой работы : суть

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)
    }
}

Edit:
Я изменил ip-адрес vm: 192.168.1.2 не 192.168.1.1

3 ответов


вам лучше сделать это по имени хоста, а не по URL. например!--2-->

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

Если вы еще не знали, имя хоста - это просто заголовок HTTP-запроса (Host: domain.com), поэтому вы можете иметь несколько имен хостов на IP (Apache называет это "именованными виртуальными хостами").

преимущество использования имен хостов, а не URL-адресов заключается в том, что веб-приложение на другом конце не знает о URL-адресах, которые вы добавляете, но должны соблюдать их, поэтому вы можете столкнуться с проблемами с URL-адресами написано веб-приложение не работает против URL-адресов, ожидаемых обратным прокси-сервером. Где в качестве прокси на основе имени хоста должны работать, поскольку большинство веб-приложений не переписывают доменное имя. (это огромное обобщение, хотя некоторые веб-приложения позволят вам добавить адрес прокси - сервера, но обычно вы столкнетесь с меньшими проблемами с именами хостов)

самая большая проблема заключается в настройке поддоменов на сервере имен. Я предполагаю, что ваши поставщики registra / DNS позволяют создавать поддомены бесплатно (большинство должно), но если вы используете что-то вроде динамического DNS с этим работает от вашего домашнего широкополосного соединения, то вы столкнетесь с проблемами, и вам придется купить свое собственное доменное имя с поддоменами CNAME'ED на ваш динамический DNS-адрес (или использовать платную учетную запись с динамическими DNS-провайдерами, если они предлагают поддомены).

и последнее, если вы смотрите в owncloud, то вы также можете взглянуть на Pydio (формально AjaxExplore). Они оба имеют разные сильные и слабые стороны, но по моему личному мнению Pydio-лучший продукт.


сделать карту, как это

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))
}

ListenAndServe

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

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

вы можете кэшировать httputil.ReverseProxy на Глобальной карте, в файле выше.

здесь SSLDocker проект видел, чтобы соответствовать вам лучше всего.


передача неправильного IP-адреса обратному прокси-серверу. Должен быть ваш VM 192.168.1.2.

на docs

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