1
0
Fork 0
promty/proxy/main.go

153 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"net/http"
"net/http/httputil"
"net/url"
"os"
"regexp"
"strings"
)
func main() {
proxy := &httputil.ReverseProxy{
Rewrite: func(r *httputil.ProxyRequest) {
host, _ := Yadro2Kernel(r.In.Host, true)
url, _ := url.Parse("https://" + host)
r.SetURL(url)
// We only support gzip decoding
r.Out.Header.Set("Accept-Encoding", "gzip")
r.Out.Header.Set("User-Agent", "ядро.орг/1.0")
},
ModifyResponse: func(r *http.Response) error {
// Disable security policy because of the domain restrictions.
r.Header.Del("Content-Security-Policy")
// Skip non-html pages.
contentType := r.Header.Get("Content-Type")
if !strings.HasPrefix(contentType, "text/") {
return nil
}
r.Header.Set("Content-Type", contentType+";charset=utf-8")
// Read response body into data. If body is encoded, decode it.
var data []byte
switch r.Header.Get("Content-Encoding") {
case "gzip":
reader, _ := gzip.NewReader(r.Body)
data, _ = io.ReadAll(reader)
r.Body.Close()
default:
data, _ = io.ReadAll(r.Body)
r.Body.Close()
}
// Rewrite 30x redirect location
locHeader := r.Header.Get("Location")
if locHeader != "" {
re := regexp.MustCompile(`https?:\/\/[A-Za-z\-\.]*.?kernel\.org\/`)
r.Header.Set("Location", string(re.ReplaceAllFunc([]byte(locHeader), func(original_raw []byte) []byte {
kernel := strings.ToLower(string(original_raw))
kernel = strings.TrimPrefix(kernel, "https://")
kernel = strings.TrimPrefix(kernel, "http://")
kernel = strings.TrimPrefix(kernel, "www.")
kernel = strings.TrimSuffix(kernel, "/")
yadro, exists := Kernel2Yadro(kernel)
if !exists {
fmt.Println("Missing:", kernel)
return original_raw
}
return []byte("https://" + yadro + "/")
})))
}
// Modify the response.
data = modifyResponse(data)
// Remove headers that mess with body encoding and set the body.
r.Header.Del("Content-Encoding")
r.Header.Del("Content-Length")
r.Body = io.NopCloser(bytes.NewReader(data))
return nil
},
}
http.ListenAndServe("0.0.0.0:80", proxy)
}
func replaceDomains(response string) string {
re := regexp.MustCompile(`(?i)[A-Za-z\-\.]*\.?kernel\.org`)
response = strings.NewReplacer(
"%3F", "?",
"%26", "&",
).Replace(response)
response = re.ReplaceAllStringFunc(response, func(original_raw string) string {
kernel := strings.ToLower(original_raw)
// Strip `www.`
kernel = strings.TrimPrefix(kernel, "www.")
yadro, exists := Kernel2Yadro(kernel)
if !exists {
fmt.Println("Missing:", kernel)
return original_raw
}
return yadro
})
return response
}
func translateWithPromtPuppies(response string) string {
// Don't try to translate empty body (30x, etc)
if len(response) == 0 {
return response
}
req, _ := http.NewRequest("POST", "http://caddy:9000/translate", strings.NewReader(response))
req.Header.Add("Content-Type", "text/html")
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Fprintln(os.Stderr, "Error in while translating", err)
return ""
}
var translated strings.Builder
io.Copy(&translated, resp.Body)
resp.Body.Close()
return translated.String()
}
func enfunnify(response string) string {
return strings.NewReplacer(
"tarball", "tar ball",
).Replace(response)
}
func modifyResponse(response []byte) []byte {
s := string(response)
s = enfunnify(s)
s = translateWithPromtPuppies(s)
s = replaceDomains(s)
return []byte(s)
}