improve webserver, add domain redirects (aliases), add tests and admin page ui to manage the config
- make builtin http handlers serve on specific domains, such as for mta-sts, so
e.g. /.well-known/mta-sts.txt isn't served on all domains.
- add logging of a few more fields in access logging.
- small tweaks/bug fixes in webserver request handling.
- add config option for redirecting entire domains to another (common enough).
- split httpserver metric into two: one for duration until writing header (i.e.
performance of server), another for duration until full response is sent to
client (i.e. performance as perceived by users).
- add admin ui, a new page for managing the configs. after making changes
and hitting "save", the changes take effect immediately. the page itself
doesn't look very well-designed (many input fields, makes it look messy). i
have an idea to improve it (explained in admin.html as todo) by making the
layout look just like the config file. not urgent though.
i've already changed my websites/webapps over.
the idea of adding a webserver is to take away a (the) reason for folks to want
to complicate their mox setup by running an other webserver on the same machine.
i think the current webserver implementation can already serve most common use
cases. with a few more tweaks (feedback needed!) we should be able to get to 95%
of the use cases. the reverse proxy can take care of the remaining 5%.
nevertheless, a next step is still to change the quickstart to make it easier
for folks to run with an existing webserver, with existing tls certs/keys.
that's how this relates to issue #5.
2023-03-02 20:15:54 +03:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/mjl-/mox/dns"
|
|
|
|
"github.com/mjl-/mox/mox-"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestServeHTTP(t *testing.T) {
|
|
|
|
os.RemoveAll("../testdata/web/data")
|
|
|
|
mox.ConfigStaticPath = "../testdata/web/mox.conf"
|
|
|
|
mox.ConfigDynamicPath = filepath.Join(filepath.Dir(mox.ConfigStaticPath), "domains.conf")
|
2023-03-06 01:56:02 +03:00
|
|
|
mox.MustLoadConfig(false)
|
improve webserver, add domain redirects (aliases), add tests and admin page ui to manage the config
- make builtin http handlers serve on specific domains, such as for mta-sts, so
e.g. /.well-known/mta-sts.txt isn't served on all domains.
- add logging of a few more fields in access logging.
- small tweaks/bug fixes in webserver request handling.
- add config option for redirecting entire domains to another (common enough).
- split httpserver metric into two: one for duration until writing header (i.e.
performance of server), another for duration until full response is sent to
client (i.e. performance as perceived by users).
- add admin ui, a new page for managing the configs. after making changes
and hitting "save", the changes take effect immediately. the page itself
doesn't look very well-designed (many input fields, makes it look messy). i
have an idea to improve it (explained in admin.html as todo) by making the
layout look just like the config file. not urgent though.
i've already changed my websites/webapps over.
the idea of adding a webserver is to take away a (the) reason for folks to want
to complicate their mox setup by running an other webserver on the same machine.
i think the current webserver implementation can already serve most common use
cases. with a few more tweaks (feedback needed!) we should be able to get to 95%
of the use cases. the reverse proxy can take care of the remaining 5%.
nevertheless, a next step is still to change the quickstart to make it easier
for folks to run with an existing webserver, with existing tls certs/keys.
that's how this relates to issue #5.
2023-03-02 20:15:54 +03:00
|
|
|
|
|
|
|
srv := &serve{
|
|
|
|
PathHandlers: []pathHandler{
|
|
|
|
{
|
|
|
|
HostMatch: func(dom dns.Domain) bool {
|
|
|
|
return strings.HasPrefix(dom.ASCII, "mta-sts.")
|
|
|
|
},
|
|
|
|
Path: "/.well-known/mta-sts.txt",
|
|
|
|
Handle: func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Write([]byte("mta-sts!"))
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Webserver: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
test := func(method, target string, expCode int, expContent string, expHeaders map[string]string) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
req := httptest.NewRequest(method, target, nil)
|
|
|
|
rw := httptest.NewRecorder()
|
|
|
|
rw.Body = &bytes.Buffer{}
|
|
|
|
srv.ServeHTTP(rw, req)
|
|
|
|
resp := rw.Result()
|
|
|
|
if resp.StatusCode != expCode {
|
|
|
|
t.Fatalf("got statuscode %d, expected %d", resp.StatusCode, expCode)
|
|
|
|
}
|
|
|
|
if expContent != "" {
|
|
|
|
s := rw.Body.String()
|
|
|
|
if s != expContent {
|
|
|
|
t.Fatalf("got response data %q, expected %q", s, expContent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for k, v := range expHeaders {
|
|
|
|
if xv := resp.Header.Get(k); xv != v {
|
|
|
|
t.Fatalf("got %q for header %q, expected %q", xv, k, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
test("GET", "http://mta-sts.mox.example/.well-known/mta-sts.txt", http.StatusOK, "mta-sts!", nil)
|
|
|
|
test("GET", "http://mox.example/.well-known/mta-sts.txt", http.StatusNotFound, "", nil) // mta-sts endpoint not in this domain.
|
|
|
|
test("GET", "http://mta-sts.mox.example/static/", http.StatusNotFound, "", nil) // static not served on this domain.
|
|
|
|
test("GET", "http://mta-sts.mox.example/other", http.StatusNotFound, "", nil)
|
|
|
|
test("GET", "http://mox.example/static/", http.StatusOK, "html\n", map[string]string{"X-Test": "mox"}) // index.html is served
|
|
|
|
test("GET", "http://mox.example/static/index.html", http.StatusOK, "html\n", map[string]string{"X-Test": "mox"})
|
|
|
|
test("GET", "http://mox.example/static/dir/", http.StatusOK, "", map[string]string{"X-Test": "mox"}) // Dir listing.
|
|
|
|
test("GET", "http://mox.example/other", http.StatusNotFound, "", nil)
|
|
|
|
}
|