X-Git-Url: http://www.git.stargrave.org/?p=tofuproxy.git;a=blobdiff_plain;f=trip.go;h=4f3e1d6de56ac6e86bf174abe481caf9227d5ae1;hp=a2e2565047626294254055d3ef3ab2f4a6a76391;hb=HEAD;hpb=2a793fabff3fefc42e99a43a7a26eee2fb98badf diff --git a/trip.go b/trip.go index a2e2565..06a6f90 100644 --- a/trip.go +++ b/trip.go @@ -1,19 +1,18 @@ -/* -tofuproxy -- HTTP proxy with TLS certificates management -Copyright (C) 2021 Sergey Matveev - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, version 3 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ +// tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU +// manager, WARC/geminispace browser +// Copyright (C) 2021-2024 Sergey Matveev +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . package tofuproxy @@ -27,8 +26,10 @@ import ( "time" "github.com/dustin/go-humanize" + "go.stargrave.org/tofuproxy/caches" "go.stargrave.org/tofuproxy/fifos" "go.stargrave.org/tofuproxy/rounds" + ttls "go.stargrave.org/tofuproxy/tls" ) var ( @@ -40,7 +41,7 @@ var ( MaxIdleConns: http.DefaultTransport.(*http.Transport).MaxIdleConns, IdleConnTimeout: http.DefaultTransport.(*http.Transport).IdleConnTimeout * 2, TLSHandshakeTimeout: time.Minute, - DialTLSContext: dialTLS, + DialTLSContext: ttls.DialTLS, ForceAttemptHTTP2: true, } proxyHeaders = map[string]struct{}{ @@ -58,10 +59,12 @@ type Round func( ) (bool, error) func roundTrip(w http.ResponseWriter, req *http.Request) { - fifos.SinkReq <- fmt.Sprintf("%s %s", req.Method, req.URL.String()) + defer req.Body.Close() + fifos.LogReq <- fmt.Sprintf("%s %s", req.Method, req.URL) host := strings.TrimSuffix(req.URL.Host, ":443") for _, round := range []Round{ - rounds.RoundNoHead, + rounds.RoundGemini, + rounds.RoundWARC, rounds.RoundDenySpy, rounds.RoundRedditOld, rounds.RoundHabrImage, @@ -74,40 +77,43 @@ func roundTrip(w http.ResponseWriter, req *http.Request) { reqFlags := []string{} unauthorized := false - authCacheM.Lock() - if creds, ok := authCache[req.URL.Host]; ok { + caches.HTTPAuthCacheM.RLock() + if creds, ok := caches.HTTPAuthCache[req.URL.Host]; ok { req.SetBasicAuth(creds[0], creds[1]) unauthorized = true } - authCacheM.Unlock() + caches.HTTPAuthCacheM.RUnlock() Retry: resp, err := transport.RoundTrip(req) if err != nil { - fifos.SinkErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error()) + fifos.LogErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error()) http.Error(w, err.Error(), http.StatusBadGateway) return } if resp.StatusCode == http.StatusUnauthorized { resp.Body.Close() - authCacheM.Lock() + caches.HTTPAuthCacheM.Lock() if unauthorized { - delete(authCache, req.URL.Host) + delete(caches.HTTPAuthCache, req.URL.Host) } else { unauthorized = true } - fifos.SinkOther <- fmt.Sprintf("%s\tauthorization required", req.URL.Host) + fifos.LogVarious <- fmt.Sprintf( + "%s %s\tHTTP authorization required", req.Method, req.URL.Host, + ) user, pass, err := authDialog(host, resp.Header.Get("WWW-Authenticate")) if err != nil { - authCacheM.Unlock() - fifos.SinkErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error()) + caches.HTTPAuthCacheM.Unlock() + fifos.LogErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } - authCache[req.URL.Host] = [2]string{user, pass} - authCacheM.Unlock() + caches.HTTPAuthCache[req.URL.Host] = [2]string{user, pass} + caches.HTTPAuthCacheM.Unlock() req.SetBasicAuth(user, pass) + fifos.LogHTTPAuth <- fmt.Sprintf("%s %s\t%s", req.Method, req.URL, user) goto Retry } if unauthorized { @@ -156,16 +162,15 @@ Retry: resp.Body.Close() msg := fmt.Sprintf( "%s %s\t%s\t%s\t%s\t%s", - req.Method, - req.URL.String(), + req.Method, req.URL, resp.Status, resp.Header.Get("Content-Type"), humanize.IBytes(uint64(n)), strings.Join(reqFlags, ","), ) if resp.StatusCode == http.StatusOK { - fifos.SinkOK <- msg + fifos.LogOK <- msg } else { - fifos.SinkOther <- msg + fifos.LogNonOK <- msg } }