]> Sergey Matveev's repositories - tofuproxy.git/blobdiff - rounds/transcodeWebP.go
Another refactor
[tofuproxy.git] / rounds / transcodeWebP.go
diff --git a/rounds/transcodeWebP.go b/rounds/transcodeWebP.go
new file mode 100644 (file)
index 0000000..ff1fd8c
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+tofuproxy -- HTTP proxy with TLS certificates management
+Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+package rounds
+
+import (
+       "fmt"
+       "io"
+       "io/ioutil"
+       "log"
+       "net/http"
+       "os"
+       "os/exec"
+       "strings"
+
+       "go.stargrave.org/tofuproxy/fifos"
+)
+
+const CmdDWebP = "dwebp"
+
+func isXombrero(req *http.Request) bool {
+       return strings.Contains(req.Header.Get("User-Agent"), "AppleWebKit/538.15")
+}
+
+func RoundTranscodeWebP(
+       host string,
+       resp *http.Response,
+       w http.ResponseWriter,
+       req *http.Request,
+) (bool, error) {
+       if resp.Header.Get("Content-Type") != "image/webp" || isXombrero(req) {
+               return true, nil
+       }
+       tmpFd, err := ioutil.TempFile("", "tofuproxy.*.webp")
+       if err != nil {
+               log.Fatalln(err)
+       }
+       defer os.Remove(tmpFd.Name())
+       defer tmpFd.Close()
+       defer resp.Body.Close()
+       if _, err = io.Copy(tmpFd, resp.Body); err != nil {
+               log.Printf("Error during %s: %+v\n", req.URL, err)
+               return false, err
+       }
+       tmpFd.Close()
+       cmd := exec.Command(CmdDWebP, tmpFd.Name(), "-o", "-")
+       data, err := cmd.Output()
+       if err != nil {
+               return false, err
+       }
+       w.Header().Add("Content-Type", "image/png")
+       w.WriteHeader(http.StatusOK)
+       w.Write(data)
+       fifos.SinkOther <- fmt.Sprintf(
+               "%s %s\t%d\tWebP transcoded to PNG",
+               req.Method,
+               req.URL.String(),
+               http.StatusOK,
+       )
+       return false, nil
+}