upload anki proxy
This commit is contained in:
commit
baa77f4468
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.log
|
||||
.idea/*
|
||||
*/.ipynb_checkpoints/*
|
||||
7
go.mod
Normal file
7
go.mod
Normal file
@ -0,0 +1,7 @@
|
||||
module zproxy
|
||||
|
||||
go 1.20
|
||||
|
||||
require go.uber.org/zap v1.25.0
|
||||
|
||||
require go.uber.org/multierr v1.10.0 // indirect
|
||||
10
go.sum
Normal file
10
go.sum
Normal file
@ -0,0 +1,10 @@
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
|
||||
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
21
http/miss.go
Normal file
21
http/miss.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
resp, err := http.Get("https://zh.xhamster.com/?ref=porndude")
|
||||
if err != nil {
|
||||
fmt.Println("http get error", err)
|
||||
return
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println("read error", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(body))
|
||||
}
|
||||
51
proxy/client.go
Normal file
51
proxy/client.go
Normal file
@ -0,0 +1,51 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"zproxy/zlog"
|
||||
)
|
||||
|
||||
type UClientProxy struct {
|
||||
ServerConn *UPacketConnection
|
||||
}
|
||||
|
||||
func NewClientProxy() *UClientProxy {
|
||||
return &UClientProxy{}
|
||||
}
|
||||
func (client *UClientProxy) ServeTCP(serverAddr string, clientAddr string) error {
|
||||
conn, err := net.Dial("tcp", serverAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
zlog.Infof("connect server %s", serverAddr)
|
||||
client.ServerConn = NewPacketConnection(conn)
|
||||
_, err = client.ServerConn.Write([]byte("anki"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
data := make([]byte, 4)
|
||||
_, err := client.ServerConn.Read(data, 0, 4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if string(data) != "anki" {
|
||||
zlog.Error("rcv package error:", data)
|
||||
client.ServerConn.Clear()
|
||||
continue
|
||||
}
|
||||
conn, err := net.Dial("tcp", clientAddr)
|
||||
if err != nil {
|
||||
zlog.Error("connect local anki error: ", err.Error(), clientAddr)
|
||||
client.ServerConn.ForwardError(err)
|
||||
continue
|
||||
}
|
||||
pc := NewPacketConnection(conn)
|
||||
client.ServerConn.Forward(pc)
|
||||
pc.Forward(client.ServerConn)
|
||||
err = pc.Close()
|
||||
if err != nil {
|
||||
zlog.Error("close local anki error: ", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
85
proxy/packetconnection.go
Normal file
85
proxy/packetconnection.go
Normal file
@ -0,0 +1,85 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"zproxy/zlog"
|
||||
)
|
||||
|
||||
type UPacketConnection struct {
|
||||
*UHttpRequest
|
||||
}
|
||||
|
||||
// 创建连接的方法
|
||||
func NewPacketConnection(conn net.Conn) *UPacketConnection {
|
||||
//初始化Conn属性
|
||||
c := &UPacketConnection{
|
||||
UHttpRequest: NewHttpRequest(conn),
|
||||
}
|
||||
return c
|
||||
}
|
||||
func (pc *UPacketConnection) Forward(target *UPacketConnection) {
|
||||
pc.DataSize = 0
|
||||
pc.IsLoadHeader = false
|
||||
for !pc.IsLoadHeader {
|
||||
data, err := pc.ReadLine()
|
||||
if err != nil {
|
||||
zlog.Error("read header line error: ", err.Error())
|
||||
return
|
||||
}
|
||||
_, err = target.Write(data)
|
||||
if err != nil {
|
||||
zlog.Error("write header line error: ", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
if pc.DataSize == 0 {
|
||||
return
|
||||
}
|
||||
data := make([]byte, 1024)
|
||||
for pc.DataSize > 0 {
|
||||
size := min(pc.DataSize, 1024)
|
||||
n, err := pc.Read(data, 0, size)
|
||||
if err != nil {
|
||||
zlog.Error("read body error: ", err.Error())
|
||||
return
|
||||
}
|
||||
pc.DataSize -= n
|
||||
zlog.Infof("read body %d %s", n, data[:n])
|
||||
_, err = target.Write(data[:n])
|
||||
if err != nil {
|
||||
zlog.Error("write body error: ", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
func (pc *UPacketConnection) Close() error {
|
||||
err := pc.Conn.Close()
|
||||
return err
|
||||
}
|
||||
func (pc *UPacketConnection) ForwardError(err error) {
|
||||
pc.DataSize = 0
|
||||
pc.IsLoadHeader = false
|
||||
zlog.Infof("forward error: ", err.Error())
|
||||
for !pc.IsLoadHeader {
|
||||
_, err := pc.ReadLine()
|
||||
if err != nil {
|
||||
zlog.Error("read header line error: ", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
for pc.DataSize > 0 {
|
||||
data := make([]byte, 1024)
|
||||
size := min(pc.DataSize, 1024)
|
||||
n, err := pc.Read(data, 0, size)
|
||||
if err != nil {
|
||||
zlog.Error("Read body error: ", err.Error())
|
||||
return
|
||||
}
|
||||
pc.DataSize -= n
|
||||
}
|
||||
err = pc.WriteError(err)
|
||||
if err != nil {
|
||||
zlog.Error("write error http error: ", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
91
proxy/reader.go
Normal file
91
proxy/reader.go
Normal file
@ -0,0 +1,91 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
func min(a int, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
type UReader struct {
|
||||
io io.Reader
|
||||
buf []byte
|
||||
r, w int
|
||||
err error
|
||||
}
|
||||
|
||||
func NewReader(io io.Reader) *UReader {
|
||||
return &UReader{
|
||||
io: io,
|
||||
buf: make([]byte, 4096),
|
||||
r: 0,
|
||||
w: 0,
|
||||
}
|
||||
}
|
||||
func (b *UReader) Read(data []byte, s int, e int) (int, error) {
|
||||
n := e - s
|
||||
rn := 0
|
||||
for rn < n {
|
||||
d := min(b.w-b.r, n-rn)
|
||||
if d > 0 {
|
||||
copy(data[s+rn:s+rn+d], b.buf[b.r:b.r+d])
|
||||
b.r += d
|
||||
rn += d
|
||||
if rn >= n {
|
||||
break
|
||||
}
|
||||
}
|
||||
err := b.fill()
|
||||
if err != nil {
|
||||
return rn, err
|
||||
}
|
||||
}
|
||||
return rn, nil
|
||||
|
||||
}
|
||||
func (b *UReader) ReadLine() ([]byte, error) {
|
||||
line, err := b.ReadSlice('\n')
|
||||
return line, err
|
||||
}
|
||||
func (b *UReader) ReadSlice(delim byte) ([]byte, error) {
|
||||
s := 0 // search start index
|
||||
for {
|
||||
// Search buffer.
|
||||
if i := bytes.IndexByte(b.buf[b.r+s:b.w], delim); i >= 0 {
|
||||
i += s + 1
|
||||
b.r += i
|
||||
return b.buf[b.r-i : b.r], nil
|
||||
}
|
||||
err := b.fill()
|
||||
if err != nil {
|
||||
return b.buf[b.r:], err
|
||||
}
|
||||
}
|
||||
}
|
||||
func (b *UReader) fill() error {
|
||||
d := b.w - b.r
|
||||
if d >= len(b.buf) {
|
||||
b.r = 0
|
||||
b.w = 0
|
||||
return ErrBufferFull
|
||||
}
|
||||
// Slide existing data to beginning.
|
||||
if b.r > 0 {
|
||||
copy(b.buf, b.buf[b.r:b.w])
|
||||
b.w -= b.r
|
||||
b.r = 0
|
||||
}
|
||||
// Read new data: try a limited number of times.
|
||||
n, err := b.io.Read(b.buf[b.w:])
|
||||
b.w += n
|
||||
return err
|
||||
}
|
||||
func (b *UReader) Clear() {
|
||||
b.r = 0
|
||||
b.w = 0
|
||||
}
|
||||
80
proxy/request.go
Normal file
80
proxy/request.go
Normal file
@ -0,0 +1,80 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UHttpRequest struct {
|
||||
Conn net.Conn
|
||||
io *UReader
|
||||
IsLoadHeader bool
|
||||
DataSize int
|
||||
}
|
||||
|
||||
func NewHttpRequest(conn net.Conn) *UHttpRequest {
|
||||
return &UHttpRequest{
|
||||
Conn: conn,
|
||||
io: NewReader(conn),
|
||||
IsLoadHeader: false,
|
||||
DataSize: 0,
|
||||
}
|
||||
}
|
||||
func (req *UHttpRequest) ReadLine() ([]byte, error) {
|
||||
line, err := req.io.ReadLine()
|
||||
if err != nil {
|
||||
return line, err
|
||||
}
|
||||
if !req.IsLoadHeader && bytes.Equal(line, []byte("\r\n")) {
|
||||
req.IsLoadHeader = true
|
||||
}
|
||||
if !req.IsLoadHeader {
|
||||
k, v, ok := bytes.Cut(line, []byte(":"))
|
||||
if !ok {
|
||||
return line, err
|
||||
}
|
||||
if bytes.Equal(k, []byte("Content-Length")) {
|
||||
nv := strings.Trim(string(v), " \r\n")
|
||||
n, err := strconv.ParseUint(nv, 10, 63)
|
||||
if err != nil {
|
||||
return line, err
|
||||
}
|
||||
req.DataSize = int(n)
|
||||
}
|
||||
}
|
||||
return line, err
|
||||
}
|
||||
func (req *UHttpRequest) Read(data []byte, s int, e int) (int, error) {
|
||||
return req.io.Read(data, s, e)
|
||||
}
|
||||
func (req *UHttpRequest) Write(data []byte) (int, error) {
|
||||
return req.Conn.Write(data)
|
||||
}
|
||||
func (req *UHttpRequest) WriteError(err error) error {
|
||||
return req.WriteHttp([]byte("HTTP/1.1 200 OK\r\n"), []byte(err.Error()))
|
||||
}
|
||||
func (req *UHttpRequest) WriteHttp(header []byte, data []byte) error {
|
||||
_, err := req.Write(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var bufBody bytes.Buffer
|
||||
bufBody.WriteString("{\n \"error\" : \"")
|
||||
bufBody.WriteString(string(data))
|
||||
bufBody.WriteString("\"\n}")
|
||||
var bufWrap bytes.Buffer
|
||||
bufWrap.WriteString("Content-Length:")
|
||||
bufWrap.WriteString(strconv.Itoa(bufBody.Len()))
|
||||
bufWrap.WriteString("\r\n\r\n")
|
||||
_, err = req.Write(bufWrap.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = req.Write(bufBody.Bytes())
|
||||
return err
|
||||
}
|
||||
func (req *UHttpRequest) Clear() {
|
||||
req.io.Clear()
|
||||
}
|
||||
71
proxy/server.go
Normal file
71
proxy/server.go
Normal file
@ -0,0 +1,71 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"zproxy/zlog"
|
||||
)
|
||||
|
||||
type UServerProxy struct {
|
||||
AnkiConn *UPacketConnection
|
||||
}
|
||||
|
||||
func NewServerProxy() *UServerProxy {
|
||||
return &UServerProxy{}
|
||||
}
|
||||
func (server *UServerProxy) NewTcpConnection(client *UPacketConnection) {
|
||||
defer func() {
|
||||
if client == server.AnkiConn {
|
||||
return
|
||||
}
|
||||
err := client.Close()
|
||||
if err != nil {
|
||||
zlog.Error("close client error: ", err)
|
||||
}
|
||||
}()
|
||||
data := []byte("anki0000")
|
||||
_, err := client.Read(data, 4, 8)
|
||||
if err != nil {
|
||||
zlog.Error("read client error: ", client.Conn.RemoteAddr(), err.Error())
|
||||
return
|
||||
}
|
||||
zlog.Infof("new client %s %s", client.Conn.RemoteAddr(), data[4:])
|
||||
if string(data[4:]) == "anki" {
|
||||
server.AnkiConn = client
|
||||
return
|
||||
}
|
||||
if server.AnkiConn == nil {
|
||||
client.ForwardError(ErrNoAnkiProxy)
|
||||
return
|
||||
}
|
||||
_, err = server.AnkiConn.Write(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
client.Forward(server.AnkiConn)
|
||||
server.AnkiConn.Forward(client)
|
||||
}
|
||||
func (server *UServerProxy) ServeTCP(listenAddr string) error {
|
||||
// listenAddr 只能填端口号
|
||||
ln, err := net.Listen("tcp", listenAddr)
|
||||
if err != nil {
|
||||
zlog.Error("listen server error: ", err.Error(), listenAddr)
|
||||
return err
|
||||
}
|
||||
zlog.Infof("listen server %s", listenAddr)
|
||||
defer func(ln net.Listener) {
|
||||
err := ln.Close()
|
||||
if err != nil {
|
||||
zlog.Error("close listen server error: ", err.Error(), listenAddr)
|
||||
}
|
||||
}(ln)
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
if IsTimeoutError(err) {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
go server.NewTcpConnection(NewPacketConnection(conn))
|
||||
}
|
||||
}
|
||||
37
proxy/type.go
Normal file
37
proxy/type.go
Normal file
@ -0,0 +1,37 @@
|
||||
package proxy
|
||||
|
||||
type timeoutError interface {
|
||||
Timeout() bool // Is it a timeout error
|
||||
}
|
||||
|
||||
// fundamental is an error that has a message and a stack, but no caller.
|
||||
type errors struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
func (e errors) Error() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
func NewError(msg string) error {
|
||||
return errors{msg: msg}
|
||||
}
|
||||
|
||||
var (
|
||||
ErrBufferFull = NewError("read: buffer full")
|
||||
ErrNoAnkiProxy = NewError("anki: no client proxy connect")
|
||||
)
|
||||
var (
|
||||
ServerAddr = ":8765"
|
||||
RemoteServerAddr = "175.24.226.114" + ServerAddr
|
||||
ClientAddr = "127.0.0.1:8765"
|
||||
)
|
||||
|
||||
// IsTimeoutError checks if the error is a timeout error
|
||||
func IsTimeoutError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
ne, ok := err.(timeoutError)
|
||||
return ok && ne.Timeout()
|
||||
}
|
||||
BIN
python/__pycache__/http.cpython-39.pyc
Normal file
BIN
python/__pycache__/http.cpython-39.pyc
Normal file
Binary file not shown.
BIN
python/__pycache__/http2.cpython-39.pyc
Normal file
BIN
python/__pycache__/http2.cpython-39.pyc
Normal file
Binary file not shown.
155
python/anki.ipynb
Normal file
155
python/anki.ipynb
Normal file
@ -0,0 +1,155 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"id": "1664172b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from http2 import *\n",
|
||||
"class AnkiClient(Http):\n",
|
||||
" def __init__(self):\n",
|
||||
" Http.__init__(self)\n",
|
||||
" self.url = 'http://127.0.0.1:8764'\n",
|
||||
" self.version = None\n",
|
||||
" def api(self, data):\n",
|
||||
" print(data)\n",
|
||||
" data = json.dumps(data)\n",
|
||||
" res = self._post(self.url, data)\n",
|
||||
" return res\n",
|
||||
" def make_version(self):\n",
|
||||
" self.version = self.api({\"action\":\"version\"})\n",
|
||||
" return self.version\n",
|
||||
" def deckNames(self):\n",
|
||||
" return self.api({\"action\":\"deckNames\"})\n",
|
||||
" def modelNames(self):\n",
|
||||
" return self.api({\"action\":\"modelNames\"})\n",
|
||||
" def modelFieldNames(self, modelName):\n",
|
||||
" return self.api({\"action\":\"modelFieldNames\", \"params\" :{\"modelName\" : modelName}})\n",
|
||||
" def addNote(self, note):\n",
|
||||
" return self.api({\"action\":\"addNote\", \"params\" : {\"note\": note}})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"id": "ee987c62",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"anki = AnkiClient()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"id": "58e77a6b",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{'action': 'deckNames'}\n",
|
||||
"_post http://127.0.0.1:8764\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"b'[\"Git\", \"\\\\u53e5\\\\u7d20\", \"\\\\u793a\\\\u4f8b\\\\u724c\\\\u7ec4\", \"\\\\u7cfb\\\\u7edf\\\\u9ed8\\\\u8ba4\", \"\\\\u82f1\\\\u8bed\", \"\\\\u8d56\\\\u4e16\\\\u96c4\\\\u97f3\\\\u6807\", \"\\\\u97f3\\\\u6807\"]'"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"t = anki.deckNames()\n",
|
||||
"t"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"id": "c3b5b237",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"b'{\\n error = \"anki: no client proxy connect\"\\n}'"
|
||||
]
|
||||
},
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"t"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"id": "53bd0e19",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"b = b'{\\n error = \"anki: no client proxy connect\"\\n}'"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"id": "9d89217c",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\n",
|
||||
" error = \"anki: no client proxy connect\"\n",
|
||||
"}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(b.decode())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "203e9f90",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
84
python/http2.py
Normal file
84
python/http2.py
Normal file
@ -0,0 +1,84 @@
|
||||
import inspect
|
||||
import json, requests , zlib
|
||||
from functools import wraps
|
||||
from http.cookiejar import LWPCookieJar
|
||||
import http.cookiejar as cookielib
|
||||
default_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\
|
||||
/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
|
||||
class Session(requests.Session):
|
||||
def __init__(self, headers={}, cookie_file=None):
|
||||
requests.Session.__init__(self)
|
||||
if cookie_file:
|
||||
self.cookies = LWPCookieJar(filename = cookie_file)
|
||||
self.cookies.load(ignore_discard = True)
|
||||
self.update(headers)
|
||||
self.auth = ('user', 'pass')
|
||||
def save(self, filename = None):
|
||||
self.cookies.save()
|
||||
def update(self, headers):
|
||||
self.headers.update(headers)
|
||||
def http_error(code):
|
||||
def _with(func):
|
||||
@wraps(func)
|
||||
def _deco(self, url):
|
||||
return func(self, url)
|
||||
_deco.__error_code__ = code
|
||||
return _deco
|
||||
return _with
|
||||
class Http():
|
||||
def __init__(self, headers = default_headers, session = None):
|
||||
session = session or Session()
|
||||
session.update(headers)
|
||||
self.session = session
|
||||
self._type = 'str'
|
||||
self._error_dict = self._get_error_dict()
|
||||
def _gets(self, url, data = None):
|
||||
res = self.session.get(url, params = data)
|
||||
self._error(res, url)
|
||||
return self._res_data(res, self._type)
|
||||
def _posts(self, url, data = None):
|
||||
res = self.session.get(url, params = data)
|
||||
self._error(res, url)
|
||||
return self._res_data(res, self._type)
|
||||
def _get(self, url, data = None):
|
||||
print("_get", url)
|
||||
res = requests.get(url, params = data, headers = self.session.headers)
|
||||
self._error(res, url)
|
||||
return self._res_data(res, self._type)
|
||||
def _post(self, url, data):
|
||||
print("_post", url)
|
||||
res = requests.get(url, data = data, headers = self.session.headers)
|
||||
self._error(res, url)
|
||||
return self._res_data(res, self._type)
|
||||
def _get_error_dict(self):
|
||||
error_dict = {}
|
||||
methods = inspect.getmembers(self, predicate=inspect.ismethod)
|
||||
for method in methods:
|
||||
error_code = getattr(method[1], '__error_code__', None)
|
||||
if error_code:
|
||||
error_dict[error_code] = method[1]
|
||||
return error_dict
|
||||
def _error(self, res, url):
|
||||
code = res.status_code
|
||||
if code == 200:
|
||||
return
|
||||
print(res.content)
|
||||
if code in self._error_dict:
|
||||
self._error_dict[code](url)
|
||||
return
|
||||
raise RuntimeError(code + '- unknown error ' + url)
|
||||
@http_error(403)
|
||||
def _error_403(self, url):
|
||||
raise RuntimeError('error:403 - Forbidden ' + url)
|
||||
@http_error(404)
|
||||
def _error_404(self, url):
|
||||
raise RuntimeError('error:404 - Not Found ' + url)
|
||||
def _res_data(self, res, _type):
|
||||
# encoding = None
|
||||
# if 'Content-Encoding' in res.headers:
|
||||
# encoding = res.headers['Content-Encoding']
|
||||
# if encoding == 'gzip':
|
||||
# res.content = zlib.decompress(res.content, 16 + zlib.MAX_WBITS)
|
||||
# if _type == 'json':
|
||||
# return json.loads(res.content)
|
||||
return res.content
|
||||
64
python/test.ipynb
Normal file
64
python/test.ipynb
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "3f40720a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import requests"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "d2986616",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<Response [200]>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"requests.get(\"http://localhost:8080/\",data = \"helloworld\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "7f2dd59b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
14
run/client/client.go
Normal file
14
run/client/client.go
Normal file
@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"zproxy/proxy"
|
||||
"zproxy/zlog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
client := proxy.NewClientProxy()
|
||||
err := client.ServeTCP(proxy.RemoteServerAddr, proxy.ClientAddr)
|
||||
if err != nil {
|
||||
zlog.Error("exist client remote proxy: ", err.Error())
|
||||
}
|
||||
}
|
||||
15
run/server/server.go
Normal file
15
run/server/server.go
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"zproxy/proxy"
|
||||
"zproxy/zlog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
server := proxy.NewServerProxy()
|
||||
err := server.ServeTCP(proxy.ServerAddr)
|
||||
if err != nil {
|
||||
zlog.Error("exist server proxy: ", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
11
run/test/test.go
Normal file
11
run/test/test.go
Normal file
@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "net/http"
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Write([]byte("ok"))
|
||||
})
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
||||
70
zlog/test
Normal file
70
zlog/test
Normal file
@ -0,0 +1,70 @@
|
||||
from .http import *
|
||||
import json,functools
|
||||
class util:
|
||||
def api(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(self,**kwargs):
|
||||
self._api({"params" : kwargs , "action":func.__name__ })
|
||||
self.res = func(self, **kwargs) or self.res
|
||||
return self.res
|
||||
return wrapper
|
||||
class AnkiClient(Http):
|
||||
util = util
|
||||
def __init__(self, url = None):
|
||||
Http.__init__(self)
|
||||
self.url = url or 'http://127.0.0.1:8765'
|
||||
self._version = None
|
||||
self.res = None
|
||||
def _api(self, data):
|
||||
if self._version and type(self._version) == int:
|
||||
data["version"] = self._version
|
||||
data = json.dumps(data)
|
||||
res = self._post(self.url, data)
|
||||
self.res = json.loads(res)
|
||||
return self.res
|
||||
@util.api
|
||||
def version(self):
|
||||
self._version = self.res
|
||||
pass
|
||||
@util.api
|
||||
def deckNames(self):
|
||||
pass
|
||||
@util.api
|
||||
def modelNames(self):
|
||||
pass
|
||||
@util.api
|
||||
def modelFieldNames(self, modelName = "示例牌组"):
|
||||
pass
|
||||
@util.api
|
||||
def modelFieldDescriptions(self, modelName = "示例牌组"):
|
||||
pass
|
||||
@util.api
|
||||
def modelTemplates(self, modelName = "示例牌组"):
|
||||
pass
|
||||
@util.api
|
||||
def addNote(self, note = {}):
|
||||
pass
|
||||
@util.api
|
||||
def findNotes(self, query = "note:basic"):
|
||||
pass
|
||||
@util.api
|
||||
def updateNote(self, note = {}):
|
||||
pass
|
||||
@util.api
|
||||
def updateNoteTags(self, note = {}, tags = []):
|
||||
pass
|
||||
@util.api
|
||||
def notesInfo(self, notes = []):
|
||||
pass
|
||||
@util.api
|
||||
def findCards(self, query = "deck:示例牌组"):
|
||||
pass
|
||||
@util.api
|
||||
def cardsInfo(self, cards = []):
|
||||
pass
|
||||
@util.api
|
||||
def updateNoteFields(self, note = {}):
|
||||
pass
|
||||
@util.api
|
||||
def createModel(self, modelName = "basic", inOrderFields = {}, cardTemplates = {}, css = None, isCloze = False):
|
||||
pass
|
||||
16
zlog/type.go
Normal file
16
zlog/type.go
Normal file
@ -0,0 +1,16 @@
|
||||
package zlog
|
||||
|
||||
import (
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// Level is type of log levels
|
||||
type Level = zapcore.Level
|
||||
|
||||
type FLogf = func(template string, args ...interface{})
|
||||
type FLog = func(args ...interface{})
|
||||
|
||||
var (
|
||||
Debugf, Infof, Warnf, Errorf, Panicf, Fatalf FLogf
|
||||
Debug, Error, Panic, Fatal FLog
|
||||
)
|
||||
98
zlog/zlog.go
Normal file
98
zlog/zlog.go
Normal file
@ -0,0 +1,98 @@
|
||||
package zlog
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg zap.Config
|
||||
logger *zap.Logger
|
||||
sugar *zap.SugaredLogger
|
||||
source string
|
||||
currentLevel Level
|
||||
)
|
||||
|
||||
func init() {
|
||||
currentLevel = zap.DebugLevel
|
||||
cfg = zap.NewDevelopmentConfig()
|
||||
cfg.Development = true
|
||||
rebuildLoggerFromCfg()
|
||||
}
|
||||
|
||||
// SetSource sets the component name (dispatcher/gate/game) of gwlog module
|
||||
func SetSource(source_ string) {
|
||||
source = source_
|
||||
rebuildLoggerFromCfg()
|
||||
}
|
||||
|
||||
func SetParseLevel(slv string) {
|
||||
lv := ParseLevel(slv)
|
||||
SetLevel(lv)
|
||||
}
|
||||
|
||||
// SetLevel sets the zlog level
|
||||
func SetLevel(lv Level) {
|
||||
currentLevel = lv
|
||||
cfg.Level.SetLevel(lv)
|
||||
}
|
||||
|
||||
// GetLevel get the current zlog level
|
||||
func GetLevel() Level {
|
||||
return currentLevel
|
||||
}
|
||||
|
||||
// SetOutput sets the output writer
|
||||
func SetOutput(outputs []string) {
|
||||
cfg.OutputPaths = outputs
|
||||
rebuildLoggerFromCfg()
|
||||
}
|
||||
|
||||
// ParseLevel converts string to Levels
|
||||
func ParseLevel(s string) Level {
|
||||
if strings.ToLower(s) == "debug" {
|
||||
return zap.DebugLevel
|
||||
} else if strings.ToLower(s) == "info" {
|
||||
return zap.InfoLevel
|
||||
} else if strings.ToLower(s) == "warn" || strings.ToLower(s) == "warning" {
|
||||
return zap.WarnLevel
|
||||
} else if strings.ToLower(s) == "error" {
|
||||
return zap.ErrorLevel
|
||||
} else if strings.ToLower(s) == "panic" {
|
||||
return zap.PanicLevel
|
||||
} else if strings.ToLower(s) == "fatal" {
|
||||
return zap.FatalLevel
|
||||
}
|
||||
Errorf("ParseLevel: unknown level: %s", s)
|
||||
return zap.DebugLevel
|
||||
}
|
||||
|
||||
func rebuildLoggerFromCfg() {
|
||||
newLogger, err := cfg.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
if logger != nil {
|
||||
logger.Sync()
|
||||
}
|
||||
logger = newLogger
|
||||
if source != "" {
|
||||
logger = logger.With(zap.String("source", source))
|
||||
}
|
||||
sugar = logger.Sugar()
|
||||
initFLog()
|
||||
}
|
||||
func initFLog() {
|
||||
Debugf = sugar.Debugf
|
||||
Infof = sugar.Infof
|
||||
Warnf = sugar.Warnf
|
||||
Errorf = sugar.Errorf
|
||||
Panicf = sugar.Panicf
|
||||
Fatalf = sugar.Fatalf
|
||||
|
||||
Debug = sugar.Debug
|
||||
Error = sugar.Error
|
||||
Panic = sugar.Panic
|
||||
Fatal = sugar.Fatal
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user