2014-01-10 4 views
8

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

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

192.168.1.1: является хозяином IP
192.168.1.2: это VM IP

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

192.168.1.2/owncloud: owncloud адрес
192.168.1.2:8080: другое приложение
.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) 
    } 
} 

Edit:
Я изменил адрес В.М. IP: 192.168.1.2 не 192.168.1.1

ответ

3

Вы бы лучше делать это по имени хоста, а не URL. например

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, указанными на вашем динамическом DNS-адресе (или использовать платный аккаунт у ваших динамических поставщиков DNS, если они предлагают субдомены).

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

+0

На самом деле, это лучшее решение для моих нужд. Спасибо за помощь ! – Amine

+1

Я также должен был сказать, что, слушая порт 80 (и, таким образом, запуская его как root), вы также должны изменить идентификатор пользователя и идентификатор группы в случае обнаружения и использования уязвимости: 'err = syscall .Setgid (daemon_group_id); err = syscall.Setuid (daemon_user_id) ' – Laurence

0

Вашего пропускания неправильного 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.

+0

Благодарим вас за ваш ответ: ip-адрес, используемый здесь, не является моей реальной конфигурацией. У меня есть исправление – Amine

+0

Я считаю, что то, что я ищу, просто невозможно без изменения веб-приложения на сервере под каталогами app1, app2, ..., а затем подключить их к моей программе Golang под портом 80 хост-машины. – Amine

+0

Как изменить заголовок ответа в обратном прокси? Например, если я хочу изменить заголовок «Сервер». – BigSack

-1

Сделать карту как этот

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 в глобальной карте, all in file выше.

Проект SSLDocker виден наилучшим образом.

Смежные вопросы