Hello! I’ve spun up a seafile container on a local docker host and am writing a reverse proxy in golang to route traffic to seafile and other containers/services on the host (based on subdomains for now). Please check out my Reverse Proxy code:
package main
import (
"fmt"
"log"
"flag"
"net/url"
"net/http"
"net/http/httputil"
"github.com/gorilla/mux"
)
/*****
* Domain name and service addresses
*****/
const (
DOMAIN = "example.com"
OCTOPRINT = "http://172.19.0.2:5000"
SEAFILE = "http://172.20.0.4:80"
)
/*****
* Update each HTTP request headers to route through the backend service URL
*****/
func mkDirector(service *url.URL) (func(r *http.Request)) {
return func(req *http.Request) {
// Log reverse proxy path
log.Println(req.RemoteAddr + " -> " + req.Host + " -> " + service.Host)
// Change HTTP headers to service path
req.Header.Add("X-Forwarded-For", req.RemoteAddr)
req.Header.Add("X-Origin-Host", service.Host)
req.Host = service.Host
req.URL.Host = service.Host
req.URL.Scheme = service.Scheme
}
}
/*****
* Initialize ServieProxy struct by converting service name into backend proxy
* for service.
*****/
func mkService(service string) (ServiceProxy) {
// Convert service string to backend service URL
var s *url.URL
var err error
if (service == "print") {
s, err = url.Parse(OCTOPRINT)
} else
if (service == "files") {
s, err = url.Parse(SEAFILE)
}
if err != nil {
log.Fatal(err)
}
// Create ServiceProxy object
sp := ServiceProxy{service: s}
director := mkDirector(s)
sp.proxy = &httputil.ReverseProxy{Director: director}
return sp
}
/*****
* Structure for each service
*****/
type ServiceProxy struct {
service *url.URL
proxy *httputil.ReverseProxy
}
func main() {
port := flag.Int("p", 8080, "port")
flag.Parse()
rt := mux.NewRouter()
s1 := rt.Host("print." + DOMAIN).Subrouter()
s2 := rt.Host("files." + DOMAIN).Subrouter()
rt.HandleFunc("/", landingPage)
s1.Handle("/", mkService("print").proxy)
s2.Handle("/", mkService("files").proxy)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), rt))
}
/*****
* Placeholder for landing page.
*****/
func landingPage(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "<h1>This is the landing page!</h1>")
}
If I curl the seafile service directly (from the docker host) I get a 200 response. And if I access the seafile port I exposed in the docker-compose.yml from browser, I get redirected to the auth screen. But if I access through the subdomain in my code, I get a 404 response, even after having the URL redirected to the “/accounts/login/?next=/” path
$ curl -I -L 172.23.0.4
HTTP/1.1 302 Found
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 05 Feb 2022 22:21:53 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Location: /accounts/login/?next=/
Vary: Accept-Language, Cookie
Content-Language: en
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 05 Feb 2022 22:21:53 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 12060
Connection: keep-alive
Expires: Sat, 05 Feb 2022 22:21:53 GMT
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Vary: Cookie, Accept-Language
Content-Language: en
Set-Cookie: sfcsrftoken=DAgNIckiQcyvy4********************8KHrYcSpvHf11HOfNu6x01bgiybpNH; expires=Sat, 04 Feb 2023 22:21:53 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Set-Cookie: sessionid=yzj9cjvh3thhx8lqudqj0tf90dqxcu1i; expires=Sun, 06 Feb 2022 22:21:53 GMT; HttpOnly; Max-Age=86400; Path=/; SameSite=Lax
This is what happens when I curl from a subdomain using golang reverse-proxy to get to seafile.
$ curl -I -L files.example.com:8080
HTTP/1.1 302 Found
Content-Language: en
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Sat, 05 Feb 2022 22:18:54 GMT
Location: /accounts/login/?next=/
Server: nginx/1.18.0 (Ubuntu)
Vary: Accept-Language, Cookie
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Sat, 05 Feb 2022 22:18:54 GMT
Content-Length: 19
I get a similar resposne from the other service already loaded (octoprint). It gives no 404, just a blank page and a 200 resposne - with same curl output for both proxy and direct.
I am wondering if this is a case where I am being blocked from accessing the services because I am on an LAN connection? I’ve been banging my head against this for a while now, any help would be GREATLY appreciated! Thanks!!