mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-22 16:07:49 +08:00
181 lines
3.9 KiB
Go
181 lines
3.9 KiB
Go
// Copyright (c) 2016-present Cloud <cloud@txthinking.com>
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of version 3 of the GNU General Public
|
|
// License as published by the Free Software Foundation.
|
|
//
|
|
// 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 <https://www.gnu.org/licenses/>.
|
|
|
|
package brook
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"text/template"
|
|
"time"
|
|
"strings"
|
|
|
|
"github.com/tdewolff/minify"
|
|
"github.com/tdewolff/minify/js"
|
|
)
|
|
|
|
type PAC struct {
|
|
Addr string
|
|
File string
|
|
Proxy string
|
|
DomainURL string
|
|
DomainData []byte
|
|
HTTPServer *http.Server
|
|
Body []byte
|
|
}
|
|
|
|
func NewPAC(addr, file, proxy, domainURL string) *PAC {
|
|
p := &PAC{
|
|
Addr: addr,
|
|
File: file,
|
|
Proxy: proxy,
|
|
DomainURL: domainURL,
|
|
}
|
|
mux := http.NewServeMux()
|
|
mux.Handle("/", p)
|
|
p.HTTPServer = &http.Server{
|
|
Addr: p.Addr,
|
|
ReadTimeout: 5 * time.Second,
|
|
WriteTimeout: 10 * time.Second,
|
|
IdleTimeout: 120 * time.Second,
|
|
MaxHeaderBytes: 1 << 20,
|
|
Handler: mux,
|
|
}
|
|
return p
|
|
}
|
|
|
|
func (p *PAC) MakeBody() (io.Reader, error) {
|
|
var err error
|
|
l := make([]string, 0)
|
|
if p.DomainURL != "" {
|
|
l, err = ReadList(p.DomainURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if p.DomainData != nil {
|
|
b := bytes.TrimSpace(p.DomainData)
|
|
b = bytes.Replace(b, []byte{0x20}, []byte{}, -1)
|
|
b = bytes.Replace(b, []byte{0x0d, 0x0a}, []byte{0x0a}, -1)
|
|
l = strings.Split(string(b), "\n")
|
|
}
|
|
t := template.New("pac")
|
|
t, err = t.Parse(tpl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
b := &bytes.Buffer{}
|
|
if err := t.Execute(b, map[string]interface{}{
|
|
"proxy": p.Proxy,
|
|
"domains": l,
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
b1 := &bytes.Buffer{}
|
|
m := minify.New()
|
|
m.AddFunc("application/javascript", js.Minify)
|
|
if err := m.Minify("application/javascript", b1, b); err != nil {
|
|
return nil, err
|
|
}
|
|
return b1, nil
|
|
}
|
|
|
|
func (p *PAC) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/x-ns-proxy-autoconfig")
|
|
w.Write(p.Body)
|
|
}
|
|
|
|
func (p *PAC) ListenAndServe() error {
|
|
r, err := p.MakeBody()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.Body, err = io.ReadAll(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return p.HTTPServer.ListenAndServe()
|
|
}
|
|
|
|
func (p *PAC) Shutdown() error {
|
|
return p.HTTPServer.Shutdown(context.Background())
|
|
}
|
|
|
|
func (p *PAC) WriteToFile() error {
|
|
r, err := p.MakeBody()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b, err := io.ReadAll(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.WriteFile(p.File, b, 0644); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *PAC) WriteToStdout() error {
|
|
r, err := p.MakeBody()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := io.Copy(os.Stdout, r); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var tpl = `
|
|
var proxy="{{.proxy}}";
|
|
|
|
var domains = {
|
|
{{range .domains}}
|
|
"{{.}}": 1,
|
|
{{end}}
|
|
};
|
|
|
|
function ip4todecimal(ip) {
|
|
var d = ip.split('.');
|
|
return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]);
|
|
}
|
|
|
|
function FindProxyForURL(url, host){
|
|
if(/\d+\.\d+\.\d+\.\d+/.test(host)){
|
|
if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
|
|
isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
|
|
isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
|
|
isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0")){
|
|
return "DIRECT";
|
|
}
|
|
return "DIRECT";
|
|
}
|
|
if (isPlainHostName(host)){
|
|
return "DIRECT";
|
|
}
|
|
|
|
var a = host.split(".");
|
|
for(var i=a.length-1; i>=0; i--){
|
|
if (domains.hasOwnProperty(a.slice(i).join("."))){
|
|
return "DIRECT";
|
|
}
|
|
}
|
|
return proxy;
|
|
}
|
|
`
|