mirror of
https://github.com/cnsilvan/UnblockNeteaseMusic.git
synced 2025-01-09 04:28:41 +08:00
init for test
This commit is contained in:
parent
e208e0b9a3
commit
273466b67c
32
app.go
Normal file
32
app.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"config"
|
||||
"fmt"
|
||||
"host"
|
||||
"proxy"
|
||||
"version"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf(`
|
||||
## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||
## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||
## ## ## ## ## ## ## ## ## ## ##
|
||||
## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||
## ## ## ## ## ## ## ## ## ## ##
|
||||
## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||
## ## ## ## ## #### ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
||||
|
||||
%s`+" by cnsilvan(https://github.com/cnsilvan/UnblockNeteaseMusic) \n", version.Version)
|
||||
fmt.Println("--------------------Version--------------------")
|
||||
fmt.Println(version.FullVersion())
|
||||
if config.ValidParams() {
|
||||
fmt.Println("--------------------Config--------------------")
|
||||
fmt.Println("port=", *config.Port)
|
||||
fmt.Println("source=", *config.Source)
|
||||
if host.InitHosts() == nil {
|
||||
proxy.InitProxy()
|
||||
}
|
||||
}
|
||||
}
|
33
build.sh
Executable file
33
build.sh
Executable file
@ -0,0 +1,33 @@
|
||||
CurrentVersion=0.1.0
|
||||
Project=UnblockNeteaseMusic
|
||||
Path="version"
|
||||
GitCommit=$(git rev-parse --short HEAD || echo unsupported)
|
||||
GoVersion=$(go version)
|
||||
BuildTime=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
platforms=("darwin/amd64")
|
||||
buildGo() {
|
||||
GOOS=$1
|
||||
GOARCH=$2
|
||||
output_name=$Project
|
||||
if [ $GOOS = "windows" ]; then
|
||||
output_name+='.exe'
|
||||
fi
|
||||
echo "Building($GOOS/$GOARCH)..."
|
||||
TargetDir=bin/$GOOS/$GOARCH
|
||||
env GOOS=$GOOS GOARCH=$GOARCH go build -ldflags "-X '$Path.Version=$CurrentVersion' -X '$Path.BuildTime=$BuildTime' -X '$Path.GoVersion=$GoVersion' -X '$Path.GitCommit=$GitCommit' -w -s" -o $TargetDir/$output_name
|
||||
if [ $? -ne 0 ]; then
|
||||
echo 'An error has occurred! Aborting the script execution...'
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
for platform in "${platforms[@]}"; do
|
||||
platform_split=(${platform//\// })
|
||||
buildGo ${platform_split[0]} ${platform_split[1]}
|
||||
done
|
||||
echo "--------------------------------------------"
|
||||
echo "Version:" $CurrentVersion
|
||||
echo "Git commit:" $GitCommit
|
||||
echo "Go version:" $GoVersion
|
||||
echo "Build Time:" $BuildTime
|
||||
echo "Build Finish"
|
||||
echo "--------------------------------------------"
|
48
src/config/config.go
Normal file
48
src/config/config.go
Normal file
@ -0,0 +1,48 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
Port = flag.String("p", "80:443", "specify server port,such as : \"80:443\"")
|
||||
Source = flag.String("o", "kuwo:kugou", "specify server source,such as : \"kuwo:kugou\"")
|
||||
)
|
||||
|
||||
func ValidParams() bool {
|
||||
flag.Parse()
|
||||
if flag.NArg() > 0 {
|
||||
fmt.Println("--------------------Invalid Params------------------------")
|
||||
fmt.Printf("Invalid params=%s, num=%d\n", flag.Args(), flag.NArg())
|
||||
for i := 0; i < flag.NArg(); i++ {
|
||||
fmt.Printf("arg[%d]=%s\n", i, flag.Arg(i))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("--------------------Port------------------------")
|
||||
ports := strings.Split(*Port, ":")
|
||||
if len(ports) < 1 {
|
||||
fmt.Printf("port param invalid: %v \n", *Port)
|
||||
return false
|
||||
}
|
||||
for _, p := range ports {
|
||||
fmt.Println(p)
|
||||
if m, _ := regexp.MatchString("^\\d+$", p); !m {
|
||||
fmt.Printf("port param invalid: %v \n", *Port)
|
||||
return false
|
||||
}
|
||||
}
|
||||
fmt.Println("--------------------Source------------------------")
|
||||
sources := strings.Split(*Source, ":")
|
||||
if len(sources) < 1 {
|
||||
fmt.Printf("source param invalid: %v \n", *Source)
|
||||
return false
|
||||
}
|
||||
for _, p := range sources {
|
||||
fmt.Println(p)
|
||||
}
|
||||
return true
|
||||
}
|
232
src/host/host.go
Normal file
232
src/host/host.go
Normal file
@ -0,0 +1,232 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ProxyIp = "127.0.0.1"
|
||||
ProxyDomain = map[string]string{
|
||||
"music.163.com": "59.111.181.38",
|
||||
"interface.music.163.com": "59.111.181.38",
|
||||
}
|
||||
//ProxyDomain = map[string]string{
|
||||
// "music.163.com": "59.111.181.35",
|
||||
// "interface.music.163.com": "59.111.181.35",
|
||||
// "interface3.music.163.com": "59.111.181.35",
|
||||
// "apm.music.163.com": "59.111.181.35",
|
||||
// "apm3.music.163.com": "59.111.181.35",
|
||||
// "music.httpdns.c.163.com": "59.111.181.35",
|
||||
// "httpdns.n.netease.com": "59.111.179.213",
|
||||
//}
|
||||
)
|
||||
|
||||
func getWinSystemDir() string {
|
||||
dir := ""
|
||||
if runtime.GOOS == "windows" {
|
||||
dir = os.Getenv("windir")
|
||||
}
|
||||
|
||||
return dir
|
||||
}
|
||||
func fileExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
//if os.IsNotExist(err) {
|
||||
// return false, nil
|
||||
//}
|
||||
return false, err
|
||||
}
|
||||
func appendToFile(fileName string, content string) error {
|
||||
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
fmt.Println("appendToFile cacheFileList.yml file create failed. err: " + err.Error())
|
||||
} else {
|
||||
defer f.Close()
|
||||
//n, _ := f.Seek(0, io.SeekEnd)
|
||||
//_, err = f.WriteAt([]byte(content), n)
|
||||
_, err = f.WriteString(content)
|
||||
if err != nil {
|
||||
fmt.Println("appendToFile write file fail:", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
func restoreHost(hostPath string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
func appendToHost(hostPath string) error {
|
||||
content := " \n# UnblockNetEaseMusic(Go)\n"
|
||||
for domain, _ := range ProxyDomain {
|
||||
content += ProxyIp + " " + domain + "\n"
|
||||
}
|
||||
return appendToFile(hostPath, content)
|
||||
}
|
||||
func backupHost(hostPath string) (bool, error) {
|
||||
containsProxyDomain := false
|
||||
host, err := os.Open(hostPath)
|
||||
if err != nil {
|
||||
fmt.Println("open file fail:", err)
|
||||
return containsProxyDomain, err
|
||||
}
|
||||
defer host.Close()
|
||||
gBackup, err := os.Create(hostPath + ".gBackup")
|
||||
if err != nil {
|
||||
fmt.Println("Open write file fail:", err)
|
||||
return containsProxyDomain, err
|
||||
}
|
||||
defer gBackup.Close()
|
||||
br := bufio.NewReader(host)
|
||||
for {
|
||||
line, _, err := br.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("read err:", err)
|
||||
return containsProxyDomain, err
|
||||
}
|
||||
newLine := string(line)
|
||||
if !containsProxyDomain {
|
||||
if strings.Contains(strings.ToUpper(newLine), strings.ToUpper("UnblockNetEaseMusic")) {
|
||||
containsProxyDomain = true
|
||||
fmt.Println("Found UnblockNetEaseMusic Line")
|
||||
}
|
||||
for domain, _ := range ProxyDomain {
|
||||
if strings.Contains(newLine, domain) {
|
||||
containsProxyDomain = true
|
||||
fmt.Println("Found ProxyDomain Line")
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = gBackup.WriteString(newLine + "\n")
|
||||
if err != nil {
|
||||
fmt.Println("write to file fail:", err)
|
||||
return containsProxyDomain, err
|
||||
}
|
||||
}
|
||||
return containsProxyDomain, nil
|
||||
}
|
||||
|
||||
// Exclude UnblockNetEaseMusic related host
|
||||
func excludeRelatedHost(hostPath string) error {
|
||||
host, err := os.Create(hostPath)
|
||||
if err != nil {
|
||||
fmt.Println("open file fail:", err)
|
||||
return err
|
||||
}
|
||||
defer host.Close()
|
||||
gBackup, err := os.Open(hostPath + ".gBackup")
|
||||
if err != nil {
|
||||
fmt.Println("Open write file fail:", err)
|
||||
return err
|
||||
}
|
||||
defer gBackup.Close()
|
||||
br := bufio.NewReader(gBackup)
|
||||
for {
|
||||
line, _, err := br.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("read err:", err)
|
||||
return err
|
||||
}
|
||||
newLine := string(line)
|
||||
needWrite := true
|
||||
for domain, _ := range ProxyDomain {
|
||||
if strings.Contains(newLine, domain) {
|
||||
needWrite = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if needWrite && strings.Contains(strings.ToUpper(newLine), strings.ToUpper("UnblockNetEaseMusic")) {
|
||||
needWrite = false
|
||||
}
|
||||
if needWrite && len(strings.TrimSpace(newLine)) == 0 {
|
||||
needWrite = false
|
||||
}
|
||||
if needWrite {
|
||||
_, err = host.WriteString(newLine + "\n")
|
||||
if err != nil {
|
||||
fmt.Println("write to file fail:", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func resolveIp(domain string) (ip string, err error) {
|
||||
|
||||
return "", nil
|
||||
}
|
||||
func resolveIps() error {
|
||||
for domain, _ := range ProxyDomain {
|
||||
rAddr, err := net.ResolveIPAddr("ip", domain)
|
||||
if err != nil {
|
||||
fmt.Printf("Fail to resolve %s, %s\n", domain, err)
|
||||
return err
|
||||
}
|
||||
if len(rAddr.IP) == 0 {
|
||||
fmt.Printf("Fail to resolve %s,IP nil\n", domain)
|
||||
return fmt.Errorf("Fail to resolve %s,Ip length==0 \n", domain)
|
||||
}
|
||||
ProxyDomain[domain] = rAddr.IP.String()
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func getHostsPath() (string, error) {
|
||||
hostsPath := "/etc/hosts"
|
||||
if runtime.GOOS == "windows" {
|
||||
hostsPath = getWinSystemDir()
|
||||
hostsPath = filepath.Join(hostsPath, "system32", "drivers", "etc", "hosts")
|
||||
} else {
|
||||
hostsPath = filepath.Join(hostsPath)
|
||||
}
|
||||
if exist, err := fileExists(hostsPath); !exist {
|
||||
fmt.Println("Not Found Host File:", hostsPath)
|
||||
return hostsPath, err
|
||||
}
|
||||
return hostsPath, nil
|
||||
}
|
||||
func InitHosts() error {
|
||||
fmt.Println("-------------------Init Host-----------------------")
|
||||
hostsPath, err := getHostsPath()
|
||||
if err == nil {
|
||||
containsProxyDomain := false
|
||||
containsProxyDomain, err = backupHost(hostsPath)
|
||||
if err == nil {
|
||||
if containsProxyDomain {
|
||||
if err = excludeRelatedHost(hostsPath); err == nil {
|
||||
err = resolveIps()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("ProxyDomain:", ProxyDomain)
|
||||
}
|
||||
} else {
|
||||
err = resolveIps()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("ProxyDomain:", ProxyDomain)
|
||||
}
|
||||
if err = appendToHost(hostsPath); err == nil {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
81
src/network/network.go
Normal file
81
src/network/network.go
Normal file
@ -0,0 +1,81 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Get(urlAddress string, host string, header map[string]string, tlsVerifyServerName bool) (*http.Response, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, urlAddress, nil)
|
||||
var resp *http.Response
|
||||
if err != nil {
|
||||
fmt.Printf("NewRequest fail:%v\n", err)
|
||||
return resp, nil
|
||||
}
|
||||
req.URL.RawQuery = req.URL.Query().Encode()
|
||||
c := http.Client{}
|
||||
if len(host) > 0 {
|
||||
req.Host = host
|
||||
req.Header.Set("host", host)
|
||||
if tlsVerifyServerName {
|
||||
tr := http.Transport{
|
||||
TLSClientConfig: &tls.Config{ServerName: req.Host},
|
||||
}
|
||||
c = http.Client{
|
||||
Transport: &tr,
|
||||
}
|
||||
}
|
||||
}
|
||||
if header != nil {
|
||||
for key, value := range header {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
}
|
||||
req.Header.Set("accept", "application/json, text/plain, */*")
|
||||
req.Header.Set("accept-encoding", "gzip, deflate")
|
||||
req.Header.Set("accept-language", "zh-CN,zh;q=0.9")
|
||||
req.Header.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
|
||||
resp, err = c.Do(req)
|
||||
if err != nil {
|
||||
fmt.Printf("http.Client.Do fail:%v\n", err)
|
||||
return resp, err
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
func GetResponseBody(resp *http.Response, keepBody bool) ([]byte, error) {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println("read body fail")
|
||||
return body, err
|
||||
}
|
||||
resp.Body.Close()
|
||||
if keepBody {
|
||||
bodyHold := ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
resp.Body = bodyHold
|
||||
}
|
||||
encode := resp.Header.Get("Content-Encoding")
|
||||
enableGzip := false
|
||||
if len(encode) > 0 && (strings.Contains(encode, "gzip") || strings.Contains(encode, "deflate")) {
|
||||
enableGzip = true
|
||||
}
|
||||
if enableGzip {
|
||||
resp.Header.Del("Content-Encoding")
|
||||
r, err := gzip.NewReader(bytes.NewReader(body))
|
||||
if err != nil {
|
||||
fmt.Println("read gzip body fail")
|
||||
return body, err
|
||||
}
|
||||
defer r.Close()
|
||||
body, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
fmt.Println("read body fail")
|
||||
return body, err
|
||||
}
|
||||
}
|
||||
return body, err
|
||||
}
|
113
src/processor/crypto/crypto.go
Normal file
113
src/processor/crypto/crypto.go
Normal file
@ -0,0 +1,113 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
)
|
||||
|
||||
// =================== CBC ======================
|
||||
func AesEncryptCBC(origData []byte, key []byte) (encrypted []byte) {
|
||||
// 分组秘钥
|
||||
// NewCipher该函数限制了输入k的长度必须为16, 24或者32
|
||||
block, _ := aes.NewCipher(key)
|
||||
blockSize := block.BlockSize() // 获取秘钥块的长度
|
||||
origData = pkcs5Padding(origData, blockSize) // 补全码
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) // 加密模式
|
||||
encrypted = make([]byte, len(origData)) // 创建数组
|
||||
blockMode.CryptBlocks(encrypted, origData) // 加密
|
||||
return encrypted
|
||||
}
|
||||
func AesDecryptCBC(encrypted []byte, key []byte) (decrypted []byte) {
|
||||
block, _ := aes.NewCipher(key) // 分组秘钥
|
||||
blockSize := block.BlockSize() // 获取秘钥块的长度
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // 加密模式
|
||||
decrypted = make([]byte, len(encrypted)) // 创建数组
|
||||
blockMode.CryptBlocks(decrypted, encrypted) // 解密
|
||||
decrypted = pkcs5UnPadding(decrypted) // 去除补全码
|
||||
return decrypted
|
||||
}
|
||||
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(ciphertext)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
func pkcs5UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
|
||||
// =================== ECB ======================
|
||||
func AesEncryptECB(origData []byte, key []byte) (encrypted []byte) {
|
||||
cipher, _ := aes.NewCipher(generateKey(key))
|
||||
length := (len(origData) + aes.BlockSize) / aes.BlockSize
|
||||
plain := make([]byte, length*aes.BlockSize)
|
||||
copy(plain, origData)
|
||||
pad := byte(len(plain) - len(origData))
|
||||
for i := len(origData); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
}
|
||||
encrypted = make([]byte, len(plain))
|
||||
// 分组分块加密
|
||||
for bs, be := 0, cipher.BlockSize(); bs <= len(origData); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
}
|
||||
|
||||
return encrypted
|
||||
}
|
||||
func AesDecryptECB(encrypted []byte, key []byte) (decrypted []byte) {
|
||||
cipher, _ := aes.NewCipher(generateKey(key))
|
||||
decrypted = make([]byte, len(encrypted))
|
||||
//
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
|
||||
trim := 0
|
||||
if len(decrypted) > 0 {
|
||||
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||
}
|
||||
|
||||
return decrypted[:trim]
|
||||
}
|
||||
func generateKey(key []byte) (genKey []byte) {
|
||||
genKey = make([]byte, 16)
|
||||
copy(genKey, key)
|
||||
for i := 16; i < len(key); {
|
||||
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
|
||||
genKey[j] ^= key[i]
|
||||
}
|
||||
}
|
||||
return genKey
|
||||
}
|
||||
|
||||
// =================== CFB ======================
|
||||
func AesEncryptCFB(origData []byte, key []byte) (encrypted []byte) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
encrypted = make([]byte, aes.BlockSize+len(origData))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted[aes.BlockSize:], origData)
|
||||
return encrypted
|
||||
}
|
||||
func AesDecryptCFB(encrypted []byte, key []byte) (decrypted []byte) {
|
||||
block, _ := aes.NewCipher(key)
|
||||
if len(encrypted) < aes.BlockSize {
|
||||
panic("ciphertext too short")
|
||||
}
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
encrypted = encrypted[aes.BlockSize:]
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted, encrypted)
|
||||
return encrypted
|
||||
}
|
238
src/processor/processor.go
Normal file
238
src/processor/processor.go
Normal file
@ -0,0 +1,238 @@
|
||||
package processor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"processor/crypto"
|
||||
"provider"
|
||||
"regexp"
|
||||
"strings"
|
||||
"utils"
|
||||
)
|
||||
|
||||
var (
|
||||
eApiKey = "e82ckenh8dichen8"
|
||||
linuxApiKey = "rFgB&h#%2?^eDg:Q"
|
||||
)
|
||||
|
||||
type Netease struct {
|
||||
Path string
|
||||
Params string
|
||||
JsonBody map[string]interface{}
|
||||
}
|
||||
|
||||
type MapType = map[string]interface{}
|
||||
type SliceType = []interface{}
|
||||
|
||||
func DecodeRequestBody(request *http.Request) *Netease {
|
||||
netease := &Netease{Path: request.RequestURI}
|
||||
requestBody, _ := ioutil.ReadAll(request.Body)
|
||||
//fmt.Println(string(requestBody))
|
||||
requestHold := ioutil.NopCloser(bytes.NewBuffer(requestBody))
|
||||
request.Body = requestHold
|
||||
pad := make([]byte, 0)
|
||||
if matched, _ := regexp.Match("/%0 +$/", requestBody); matched {
|
||||
pad = requestBody
|
||||
}
|
||||
if netease.Path == "/api/linux/forward" {
|
||||
requestBodyH := make([]byte, len(requestBody))
|
||||
length, _ := hex.Decode(requestBodyH, requestBody[8:len(requestBody)-len(pad)])
|
||||
decryptECBBytes := crypto.AesDecryptECB(requestBodyH[:length], []byte(linuxApiKey))
|
||||
var result MapType
|
||||
d := json.NewDecoder(bytes.NewReader(decryptECBBytes))
|
||||
d.UseNumber()
|
||||
d.Decode(&result)
|
||||
if utils.Exist("url", result) && utils.Exist("path", result["url"].(MapType)) {
|
||||
netease.Path = result["url"].(MapType)["path"].(string)
|
||||
}
|
||||
netease.Params = result["params"].(string)
|
||||
fmt.Println("forward")
|
||||
//fmt.Printf("path:%s \nparams:%s\n", netease.Path, netease.Params)
|
||||
} else {
|
||||
requestBodyH := make([]byte, len(requestBody))
|
||||
length, _ := hex.Decode(requestBodyH, requestBody[7:len(requestBody)-len(pad)])
|
||||
decryptECBBytes := crypto.AesDecryptECB(requestBodyH[:length], []byte(eApiKey))
|
||||
decryptString := string(decryptECBBytes)
|
||||
data := strings.Split(decryptString, "-36cd479b6b5-")
|
||||
netease.Path = data[0]
|
||||
netease.Params = data[1]
|
||||
//fmt.Printf("path:%s \nparams:%s\n", netease.Path, netease.Params)
|
||||
}
|
||||
|
||||
return netease
|
||||
}
|
||||
func DecodeResponseBody(response *http.Response, netease *Netease) {
|
||||
if response.StatusCode == 200 {
|
||||
encode := response.Header.Get("Content-Encoding")
|
||||
enableGzip := false
|
||||
if len(encode) > 0 && (strings.Contains(encode, "gzip") || strings.Contains(encode, "deflate")) {
|
||||
enableGzip = true
|
||||
}
|
||||
body, _ := ioutil.ReadAll(response.Body)
|
||||
if len(body) > 0 {
|
||||
decryptECBBytes := body
|
||||
if enableGzip {
|
||||
r, _ := gzip.NewReader(bytes.NewReader(decryptECBBytes))
|
||||
defer r.Close()
|
||||
decryptECBBytes, _ = ioutil.ReadAll(r)
|
||||
}
|
||||
decryptECBBytes = crypto.AesDecryptECB(decryptECBBytes, []byte(eApiKey))
|
||||
result := utils.ParseJson(decryptECBBytes)
|
||||
modified := false
|
||||
if strings.Contains(netease.Path, "manipulate") {
|
||||
|
||||
} else if strings.EqualFold(netease.Path, "/api/song/like") {
|
||||
} else if strings.Contains(netease.Path, "url") {
|
||||
fmt.Println(netease.Path)
|
||||
if value, ok := result["data"]; ok {
|
||||
switch value.(type) {
|
||||
case SliceType:
|
||||
if strings.Contains(netease.Path, "download") {
|
||||
for index, data := range value.(SliceType) {
|
||||
if index == 0 {
|
||||
modified = searchGreySong(data.(MapType)) || modified
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
modified = searchGreySongs(value.(SliceType)) || modified
|
||||
}
|
||||
case MapType:
|
||||
modified = searchGreySong(value.(MapType)) || modified
|
||||
default:
|
||||
}
|
||||
}
|
||||
modifiedJson, _ := json.Marshal(result)
|
||||
fmt.Println(string(modifiedJson))
|
||||
}
|
||||
if processMapJson(result) || modified {
|
||||
response.Header.Del("transfer-encoding")
|
||||
response.Header.Del("content-encoding")
|
||||
response.Header.Del("content-length")
|
||||
netease.JsonBody = result
|
||||
fmt.Println("NeedRepackage")
|
||||
modifiedJson, _ := json.Marshal(result)
|
||||
//fmt.Println(string(modifiedJson))
|
||||
encryptedJson := crypto.AesEncryptECB(modifiedJson, []byte(eApiKey))
|
||||
response.Body = ioutil.NopCloser(bytes.NewBuffer(encryptedJson))
|
||||
} else {
|
||||
//fmt.Println(string(body))
|
||||
responseHold := ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
response.Body = responseHold
|
||||
}
|
||||
|
||||
} else {
|
||||
responseHold := ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
response.Body = responseHold
|
||||
}
|
||||
} else {
|
||||
//body, _ := ioutil.ReadAll(response.Body)
|
||||
//responseHold := ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
//response.Body = responseHold
|
||||
//fmt.Println(string(body))
|
||||
}
|
||||
}
|
||||
func searchGreySongs(data SliceType) bool {
|
||||
modified := false
|
||||
for _, value := range data {
|
||||
switch value.(type) {
|
||||
case MapType:
|
||||
modified = searchGreySong(value.(MapType)) || modified
|
||||
}
|
||||
}
|
||||
return modified
|
||||
}
|
||||
func searchGreySong(data MapType) bool {
|
||||
modified := false
|
||||
if data["url"] == nil {
|
||||
data["flag"] = 0
|
||||
song := provider.Find(data["id"].(json.Number).String())
|
||||
//modifiedJson, _ := json.Marshal(song)
|
||||
//fmt.Println(string(modifiedJson))
|
||||
if song.Size > 0 {
|
||||
modified = true
|
||||
if song.Br == 999000 {
|
||||
data["type"] = "flac"
|
||||
} else {
|
||||
data["type"] = "mp3"
|
||||
}
|
||||
data["url"] = song.Url
|
||||
if len(song.Md5) > 0 {
|
||||
data["md5"] = song.Md5
|
||||
} else {
|
||||
h := md5.New()
|
||||
h.Write([]byte(song.Url))
|
||||
data["md5"] = hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
if song.Br > 0 {
|
||||
data["br"] = song.Br
|
||||
} else {
|
||||
data["br"] = 128000
|
||||
}
|
||||
data["size"] = song.Size
|
||||
data["freeTrialInfo"] = nil
|
||||
data["code"] = 200
|
||||
}
|
||||
|
||||
}
|
||||
return modified
|
||||
}
|
||||
func processSliceJson(jsonSlice SliceType) bool {
|
||||
needModify := false
|
||||
for _, value := range jsonSlice {
|
||||
switch value.(type) {
|
||||
case MapType:
|
||||
needModify = processMapJson(value.(MapType)) || needModify
|
||||
|
||||
case SliceType:
|
||||
needModify = processSliceJson(value.(SliceType)) || needModify
|
||||
|
||||
default:
|
||||
//fmt.Printf("index(%T):%v\n", index, index)
|
||||
//fmt.Printf("value(%T):%v\n", value, value)
|
||||
}
|
||||
}
|
||||
return needModify
|
||||
}
|
||||
func processMapJson(jsonMap MapType) bool {
|
||||
needModify := false
|
||||
if utils.Exists([]string{"st", "subp", "pl", "dl"}, jsonMap) {
|
||||
if v, _ := jsonMap["st"]; v.(json.Number).String() != "0" {
|
||||
//open grep song
|
||||
jsonMap["st"] = 0
|
||||
needModify = true
|
||||
}
|
||||
if v, _ := jsonMap["subp"]; v.(json.Number).String() != "1" {
|
||||
jsonMap["subp"] = 1
|
||||
needModify = true
|
||||
}
|
||||
if v, _ := jsonMap["pl"]; v.(json.Number).String() == "0" {
|
||||
jsonMap["pl"] = 320000
|
||||
needModify = true
|
||||
}
|
||||
if v, _ := jsonMap["dl"]; v.(json.Number).String() == "0" {
|
||||
jsonMap["dl"] = 320000
|
||||
needModify = true
|
||||
}
|
||||
}
|
||||
for _, value := range jsonMap {
|
||||
switch value.(type) {
|
||||
case MapType:
|
||||
needModify = processMapJson(value.(MapType)) || needModify
|
||||
case SliceType:
|
||||
needModify = processSliceJson(value.(SliceType)) || needModify
|
||||
default:
|
||||
//if key == "fee" && value.(json.Number).String() != "0" {
|
||||
// jsonMap[key] = 0
|
||||
// needModify = true
|
||||
//}
|
||||
}
|
||||
}
|
||||
return needModify
|
||||
}
|
69
src/provider/kuwo/kuwo.go
Normal file
69
src/provider/kuwo/kuwo.go
Normal file
@ -0,0 +1,69 @@
|
||||
package kuwo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"network"
|
||||
"strings"
|
||||
"utils"
|
||||
)
|
||||
|
||||
func SearchSong(key map[string]interface{}) string {
|
||||
keyword := key["keyword"].(string)
|
||||
token := getToken(keyword)
|
||||
header := make(map[string]string, 3)
|
||||
header["referer"] = "http://www.kuwo.cn/search/list?key=" + url.QueryEscape(keyword)
|
||||
header["csrf"] = token
|
||||
header["cookie"] = "kw_token=" + token
|
||||
resp, err := network.Get("http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key="+keyword+"&pn=1&rn=30", "kuwo.cn", header, false)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return ""
|
||||
}
|
||||
body, err := network.GetResponseBody(resp, false)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return ""
|
||||
}
|
||||
result := utils.ParseJson(body)
|
||||
var musicId = ""
|
||||
if result["data"] != nil && result["data"].(map[string]interface{}) != nil && len(result["data"].(map[string]interface{})["list"].([]interface{})) > 0 {
|
||||
matched := result["data"].(map[string]interface{})["list"].([]interface{})[0]
|
||||
if matched != nil && matched.(map[string]interface{})["musicrid"] != nil {
|
||||
musicrid := matched.(map[string]interface{})["musicrid"].(string)
|
||||
musicSlice := strings.Split(musicrid, "_")
|
||||
musicId = musicSlice[len(musicSlice)-1]
|
||||
}
|
||||
}
|
||||
if len(musicId) > 0 {
|
||||
resp, err = network.Get("http://antiserver.kuwo.cn/anti.s?type=convert_url&format=mp3&response=url&rid=MUSIC_"+musicId, "antiserver.kuwo.cn", nil, false)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return ""
|
||||
}
|
||||
body, err = network.GetResponseBody(resp, false)
|
||||
address := string(body)
|
||||
if strings.Index(address, "http") == 0 {
|
||||
return address
|
||||
}
|
||||
|
||||
}
|
||||
return ""
|
||||
|
||||
}
|
||||
func getToken(keyword string) string {
|
||||
var token = ""
|
||||
resp, err := network.Get("http://kuwo.cn/search/list?key="+keyword, "kuwo.cn", nil, false)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return token
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
cookies := resp.Header.Get("set-cookie")
|
||||
if strings.Contains(cookies, "kw_token") {
|
||||
cookies = utils.ReplaceAll(cookies, ";.*", "")
|
||||
splitSlice := strings.Split(cookies, "=")
|
||||
token = splitSlice[len(splitSlice)-1]
|
||||
}
|
||||
return token
|
||||
}
|
201
src/provider/provider.go
Normal file
201
src/provider/provider.go
Normal file
@ -0,0 +1,201 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"host"
|
||||
"network"
|
||||
"provider/kuwo"
|
||||
"strconv"
|
||||
"strings"
|
||||
"utils"
|
||||
)
|
||||
|
||||
type Song struct {
|
||||
Size int64
|
||||
Br int
|
||||
Url string
|
||||
Md5 string
|
||||
}
|
||||
type MapType = map[string]interface{}
|
||||
type SliceType = []interface{}
|
||||
|
||||
var Cache = make(map[string]Song)
|
||||
|
||||
func Find(id string) Song {
|
||||
fmt.Println("find song info,id:", id)
|
||||
if song,ok:=Cache[id];ok{
|
||||
fmt.Println("hit cache:", utils.ToJson(song))
|
||||
return song
|
||||
}
|
||||
|
||||
var songT Song
|
||||
resp, err := network.Get("https://"+host.ProxyDomain["music.163.com"]+"/api/song/detail?ids=["+id+"]", "music.163.com", nil, true)
|
||||
if err != nil {
|
||||
return songT
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == 200 {
|
||||
body, err2 := network.GetResponseBody(resp, false)
|
||||
if err2 != nil {
|
||||
fmt.Println("GetResponseBody fail")
|
||||
return songT
|
||||
}
|
||||
var oJson MapType
|
||||
d := json.NewDecoder(bytes.NewReader(body))
|
||||
d.UseNumber()
|
||||
d.Decode(&oJson)
|
||||
if oJson["songs"] != nil {
|
||||
song := oJson["songs"].(SliceType)[0]
|
||||
var modifiedJson = make(MapType, 6)
|
||||
var artists []string
|
||||
switch song.(type) {
|
||||
case MapType:
|
||||
modifiedJson["id"] = song.(MapType)["id"]
|
||||
modifiedJson["name"] = song.(MapType)["name"]
|
||||
modifiedJson["alias"] = song.(MapType)["alias"]
|
||||
modifiedJson["duration"] = song.(MapType)["duration"]
|
||||
modifiedJson["album"] = make(MapType, 2)
|
||||
modifiedJson["album"].(MapType)["id"] = song.(MapType)["album"].(MapType)["id"]
|
||||
modifiedJson["album"].(MapType)["name"] = song.(MapType)["album"].(MapType)["name"]
|
||||
switch song.(MapType)["artists"].(type) {
|
||||
case SliceType:
|
||||
length := len(song.(MapType)["artists"].(SliceType))
|
||||
modifiedJson["artists"] = make(SliceType, length)
|
||||
artists = make([]string, length)
|
||||
for index, value := range song.(MapType)["artists"].(SliceType) {
|
||||
if modifiedJson["artists"].(SliceType)[index] == nil {
|
||||
modifiedJson["artists"].(SliceType)[index] = make(MapType, 2)
|
||||
}
|
||||
modifiedJson["artists"].(SliceType)[index].(MapType)["id"] = value.(MapType)["id"]
|
||||
modifiedJson["artists"].(SliceType)[index].(MapType)["name"] = value.(MapType)["name"]
|
||||
artists[index] = value.(MapType)["name"].(string)
|
||||
}
|
||||
|
||||
}
|
||||
default:
|
||||
|
||||
}
|
||||
if modifiedJson["name"] != nil {
|
||||
modifiedJson["name"] = utils.ReplaceAll(modifiedJson["name"].(string), `\s*cover[::\s][^)]+)`, "")
|
||||
modifiedJson["name"] = utils.ReplaceAll(modifiedJson["name"].(string), `\(\s*cover[::\s][^\)]+\)`, "")
|
||||
}
|
||||
modifiedJson["keyword"] = modifiedJson["name"].(string) + " - " + strings.Join(artists, " / ")
|
||||
songUrl := searchSong(modifiedJson)
|
||||
songS := processSong(songUrl)
|
||||
if songS.Size > 0 {
|
||||
fmt.Println(utils.ToJson(songS))
|
||||
Cache[id] = songS
|
||||
return songS
|
||||
|
||||
}
|
||||
fmt.Println(utils.ToJson(modifiedJson))
|
||||
return songT
|
||||
} else {
|
||||
return songT
|
||||
}
|
||||
} else {
|
||||
return songT
|
||||
}
|
||||
|
||||
}
|
||||
func searchSong(key MapType) string {
|
||||
//cache after
|
||||
return kuwo.SearchSong(key)
|
||||
|
||||
}
|
||||
func processSong(songUrl string) Song {
|
||||
var song Song
|
||||
if len(songUrl) > 0 {
|
||||
header := make(map[string]string, 1)
|
||||
header["range"] = "bytes=0-8191"
|
||||
resp, err := network.Get(songUrl, "", header, false)
|
||||
if err != nil {
|
||||
fmt.Println("processSong fail:", err)
|
||||
return song
|
||||
}
|
||||
if resp.StatusCode > 199 && resp.StatusCode < 300 {
|
||||
if strings.Contains(songUrl, "qq.com") {
|
||||
song.Md5 = resp.Header.Get("server-md5")
|
||||
} else if strings.Contains(songUrl, "xiami.net") || strings.Contains(songUrl, "qianqian.com") {
|
||||
song.Md5 = strings.ToLower(utils.ReplaceAll(resp.Header.Get("etag"), `/"/g`, ""))
|
||||
//.replace(/"/g, '').toLowerCase()
|
||||
}
|
||||
size := resp.Header.Get("content-range")
|
||||
if len(size) > 0 {
|
||||
sizeSlice := strings.Split(size, "/")
|
||||
if len(sizeSlice) > 0 {
|
||||
size = sizeSlice[len(sizeSlice)-1]
|
||||
}
|
||||
} else {
|
||||
size = resp.Header.Get("content-length")
|
||||
if len(size) < 1 {
|
||||
size = "0"
|
||||
}
|
||||
}
|
||||
song.Size, _ = strconv.ParseInt(size, 10, 64)
|
||||
song.Url = songUrl
|
||||
if resp.Header.Get("content-length") == "8192" {
|
||||
body, err := network.GetResponseBody(resp, false)
|
||||
if err != nil {
|
||||
fmt.Println("song GetResponseBody error:", err)
|
||||
return song
|
||||
}
|
||||
bitrate := decodeBitrate(body)
|
||||
if bitrate > 0 && bitrate < 500 {
|
||||
song.Br = bitrate * 1000
|
||||
}
|
||||
}
|
||||
//song.url = response.url.href
|
||||
}
|
||||
}
|
||||
return song
|
||||
}
|
||||
func decodeBitrate(data []byte) int {
|
||||
bitRateMap := map[int]map[int][]int{
|
||||
0: {
|
||||
3: {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 500},
|
||||
2: {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 500},
|
||||
1: {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 500},
|
||||
},
|
||||
3: {
|
||||
3: {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 500},
|
||||
2: {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 500},
|
||||
1: {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 500},
|
||||
},
|
||||
2: {
|
||||
3: {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 500},
|
||||
2: {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 500},
|
||||
1: {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 500},
|
||||
},
|
||||
}
|
||||
|
||||
var pointer = 0
|
||||
if strings.EqualFold(string(data[0:4]), "fLaC") {
|
||||
return 999
|
||||
}
|
||||
if strings.EqualFold(string(data[0:3]), "ID3") {
|
||||
pointer = 6
|
||||
var size = 0
|
||||
for index, value := range data[pointer : pointer+4] {
|
||||
size = size + int((value&0x7f)<<(7*(3-index)))
|
||||
}
|
||||
pointer = 10 + size
|
||||
}
|
||||
|
||||
header := data[pointer : pointer+4]
|
||||
// https://www.allegro.cc/forums/thread/591512/674023
|
||||
if len(header) == 4 &&
|
||||
header[0] == 0xff &&
|
||||
((header[1]>>5)&0x7) == 0x7 &&
|
||||
((header[1]>>1)&0x3) != 0 &&
|
||||
((header[2]>>4)&0xf) != 0xf &&
|
||||
((header[2]>>2)&0x3) != 0x3 {
|
||||
version := (header[1] >> 3) & 0x3
|
||||
layer := (header[1] >> 1) & 0x3
|
||||
bitrate := header[2] >> 4
|
||||
return bitRateMap[int(version)][int(layer)][int(bitrate)]
|
||||
}
|
||||
return 0
|
||||
}
|
163
src/proxy/proxy.go
Normal file
163
src/proxy/proxy.go
Normal file
@ -0,0 +1,163 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"host"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"processor"
|
||||
"strings"
|
||||
"time"
|
||||
"utils"
|
||||
)
|
||||
|
||||
type HttpHandler struct{}
|
||||
|
||||
var (
|
||||
///api/song/enhance/player/url
|
||||
///eapi/mlivestream/entrance/playlist/get
|
||||
Path = []string{"/eapi/batch",
|
||||
"/eapi/album/privilege",
|
||||
"/eapi/cloudsearch/pc",
|
||||
"/eapi/playlist/privilege",
|
||||
"/eapi/song/enhance/player/url",
|
||||
"/eapi/v1/playlist/manipulate/tracks", //download music
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
func InitProxy() {
|
||||
fmt.Println("-------------------Init Proxy-----------------------")
|
||||
//tlsBytes("server.crt", "server.key")
|
||||
go startTlsServer(":443", "./server.crt", "./server.key", &HttpHandler{})
|
||||
startServer(":80", &HttpHandler{})
|
||||
}
|
||||
func (h *HttpHandler) ServeHTTP(resp http.ResponseWriter, request *http.Request) {
|
||||
fmt.Println(request.Host)
|
||||
fmt.Println(request.URL.String())
|
||||
fmt.Println(request.RequestURI)
|
||||
if proxyDomain, ok := host.ProxyDomain[request.Host]; ok {
|
||||
scheme := "http://"
|
||||
if request.TLS != nil {
|
||||
scheme = "https://"
|
||||
}
|
||||
requestURI := request.RequestURI
|
||||
request.Header.Del("x-napm-retry")
|
||||
request.Header.Add("X-Real-IP", "118.88.88.88")
|
||||
if strings.Contains(requestURI, "http") {
|
||||
requestURI = strings.ReplaceAll(requestURI, scheme+request.Host, "")
|
||||
}
|
||||
remote, err := url.Parse(scheme + proxyDomain + requestURI)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
proxy := httputil.NewSingleHostReverseProxy(remote)
|
||||
needTransport := false
|
||||
for _, path := range Path {
|
||||
if strings.Contains(request.RequestURI, path) {
|
||||
needTransport = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if needTransport && request.Method == http.MethodPost {
|
||||
proxy.Transport = &capturedTransport{}
|
||||
fmt.Printf("Transport:%s(%s)\n", remote, request.Host)
|
||||
} else {
|
||||
proxy.Transport = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
TLSClientConfig:
|
||||
&tls.Config{ServerName: request.Host},
|
||||
}
|
||||
fmt.Printf("Direct:%s(%s)\n", remote, request.Host)
|
||||
}
|
||||
proxy.ServeHTTP(resp, request)
|
||||
} else {
|
||||
scheme := "http://"
|
||||
if request.TLS != nil {
|
||||
scheme = "https://"
|
||||
}
|
||||
requestURI := request.RequestURI
|
||||
request.Header.Del("x-napm-retry")
|
||||
request.Header.Add("X-Real-IP", "118.88.88.88")
|
||||
if !strings.Contains(requestURI, "http") {
|
||||
requestURI = scheme + request.Host + requestURI
|
||||
}
|
||||
request.Header.Del("x-napm-retry")
|
||||
request.Header.Add("X-Real-IP", "118.88.88.88")
|
||||
remote, err := url.Parse(requestURI)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
proxy := httputil.NewSingleHostReverseProxy(remote)
|
||||
fmt.Printf("Direct:%s\n", remote)
|
||||
proxy.ServeHTTP(resp, request)
|
||||
}
|
||||
}
|
||||
|
||||
type capturedTransport struct {
|
||||
// Uncomment this if you want to capture the transport
|
||||
// CapturedTransport http.RoundTripper
|
||||
}
|
||||
|
||||
func (t *capturedTransport) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
netease := processor.DecodeRequestBody(request)
|
||||
response, err := http.DefaultTransport.RoundTrip(request)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return response, err
|
||||
}
|
||||
processor.DecodeResponseBody(response, netease)
|
||||
return response, err
|
||||
}
|
||||
|
||||
func startTlsServer(addr, certFile, keyFile string, handler http.Handler) {
|
||||
fmt.Printf("starting TLS Server %s\n", addr)
|
||||
currentPath, error := utils.GetCurrentPath()
|
||||
if error != nil {
|
||||
fmt.Println(error)
|
||||
currentPath = ""
|
||||
}
|
||||
//fmt.Println(currentPath)
|
||||
certFile, _ = filepath.Abs(currentPath + certFile)
|
||||
keyFile, _ = filepath.Abs(currentPath + keyFile)
|
||||
s := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: handler,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
err := s.ListenAndServeTLS(certFile, keyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
func startServer(addr string, handler http.Handler) {
|
||||
fmt.Printf("starting Server %s\n", addr)
|
||||
s := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: handler,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
err := s.ListenAndServe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
64
src/utils/utils.go
Normal file
64
src/utils/utils.go
Normal file
@ -0,0 +1,64 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ReplaceAll(str string, expr string, replaceStr string) string {
|
||||
reg := regexp.MustCompile(expr)
|
||||
str = reg.ReplaceAllString(str, replaceStr)
|
||||
return str
|
||||
}
|
||||
func ParseJson(data []byte) map[string]interface{} {
|
||||
var result map[string]interface{}
|
||||
d := json.NewDecoder(bytes.NewReader(data))
|
||||
d.UseNumber()
|
||||
d.Decode(&result)
|
||||
return result
|
||||
}
|
||||
func ToJson(object interface{}) string {
|
||||
json, err := json.Marshal(object)
|
||||
if err != nil {
|
||||
fmt.Println("ToJson Error:",err)
|
||||
return "{}"
|
||||
}
|
||||
return string(json)
|
||||
}
|
||||
func Exists(keys []string, h map[string]interface{}) bool {
|
||||
for _, key := range keys {
|
||||
if !Exist(key, h) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
func Exist(key string, h map[string]interface{}) bool {
|
||||
_, ok := h[key]
|
||||
return ok
|
||||
}
|
||||
func GetCurrentPath() (string, error) {
|
||||
file, err := exec.LookPath(os.Args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
path, err := filepath.Abs(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
i := strings.LastIndex(path, "/")
|
||||
if i < 0 {
|
||||
i = strings.LastIndex(path, "\\")
|
||||
}
|
||||
if i < 0 {
|
||||
return "", errors.New(`error: Can't find "/" or "\".`)
|
||||
}
|
||||
return string(path[0 : i+1]), nil
|
||||
}
|
20
src/version/version.go
Normal file
20
src/version/version.go
Normal file
@ -0,0 +1,20 @@
|
||||
package version
|
||||
|
||||
import "fmt"
|
||||
|
||||
var (
|
||||
Version string
|
||||
|
||||
//will be overwritten automatically by the build system
|
||||
GitCommit string
|
||||
GoVersion string
|
||||
BuildTime string
|
||||
)
|
||||
|
||||
func FullVersion() string {
|
||||
return fmt.Sprintf("Version: %6s \nGit commit: %6s \nGo version: %6s \nBuild time: %6s \n",
|
||||
Version, GitCommit, GoVersion, BuildTime)
|
||||
}
|
||||
func AppVersion() string {
|
||||
return Version
|
||||
}
|
Loading…
Reference in New Issue
Block a user