This commit is contained in:
eson 2023-07-17 19:43:43 +08:00
parent 73ce1e6db3
commit 4d9f14eb30
13 changed files with 398 additions and 39 deletions

20
go.mod
View File

@ -13,14 +13,20 @@ require (
github.com/stripe/stripe-go/v74 v74.22.0
github.com/zeromicro/go-zero v1.5.2
golang.org/x/image v0.0.0-20190802002840-cff245a6509b
golang.org/x/oauth2 v0.10.0
gorm.io/driver/mysql v1.5.1
gorm.io/gorm v1.25.1
)
require (
cloud.google.com/go/compute v1.20.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/schollz/progressbar v1.0.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
)
require (
@ -68,11 +74,11 @@ require (
go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/automaxprocs v1.5.2 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0
google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197 // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v2 v2.4.0
)

38
go.sum
View File

@ -19,6 +19,10 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@ -105,8 +109,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -353,14 +357,16 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -405,8 +411,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -419,8 +425,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -491,6 +497,8 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -522,8 +530,12 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197 h1:BwjeHhu4HS48EZmu1nS7flldBIDPC3qn+HqaSQ1K4x8=
google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -540,8 +552,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -555,8 +567,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

View File

@ -10,11 +10,13 @@ import (
"gopkg.in/yaml.v2"
)
// Config 结构体用于解析yaml配置文件
type Config struct {
Host string `yaml:"Host"`
Port int `yaml:"Port"`
}
// Result 结构体用于存储解析结果
type Result struct {
FolderName string
Host string
@ -22,6 +24,7 @@ type Result struct {
PrefixRoute map[string]bool
}
// GetZeroInfo 遍历指定目录,并解析相关信息
func GetZeroInfo(rootDir string) (results []*Result) {
entries, err := ioutil.ReadDir(rootDir)
if err != nil {
@ -29,21 +32,21 @@ func GetZeroInfo(rootDir string) (results []*Result) {
}
for _, entry := range entries {
// 只处理目录类型
if entry.IsDir() {
result, err := findFoldersAndExtractInfo(rootDir, entry)
if err != nil {
log.Fatal(err)
}
results = append(results, result)
}
}
return
}
// findFoldersAndExtractInfo 查找目录并提取信息
func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, error) {
var result *Result
@ -55,6 +58,7 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
return err
}
// 跳过非目录类型
if !info.IsDir() {
return nil
}
@ -64,10 +68,12 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
return err
}
// 跳过非当前目录的子目录
if strings.Contains(relPath, string(os.PathSeparator)) {
return filepath.SkipDir
}
// 读取配置文件
configPath := filepath.Join(path, "etc", folderName+".yaml")
routesPath := filepath.Join(path, "internal", "handler", "routes.go")
@ -82,6 +88,7 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
return err
}
// 读取路由文件
routesContent, err := ioutil.ReadFile(routesPath)
if err != nil {
return err
@ -89,6 +96,7 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
PrefixRoute := extractPrefixRouteValues(string(routesContent))
// 构建结果
result = &Result{
FolderName: folderName,
Host: config.Host,
@ -106,11 +114,13 @@ func findFoldersAndExtractInfo(rootDir string, entry os.FileInfo) (*Result, erro
return result, nil
}
// extractPrefixRouteValues 提取路由前缀
func extractPrefixRouteValues(content string) map[string]bool {
lines := strings.Split(content, "\n")
var prefixPath map[string]bool = make(map[string]bool)
for _, line := range lines {
// 查找包含 "Path:" 的行
if strings.Contains(line, "Path:") {
path := strings.TrimSpace(strings.TrimPrefix(line, "Path:"))
paths := strings.Split(strings.Trim(path, `"`), "/")

View File

@ -13,8 +13,10 @@ import (
"time"
)
// Backend结构体
var Backends []*Backend
// 设置跨域请求
func SetCors(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
@ -29,9 +31,11 @@ func SetCors(w http.ResponseWriter, r *http.Request) {
}
}
// 存储路径的并发安全的Map
var pathdict sync.Map = sync.Map{}
func main() {
// 将静态资源路径存储到pathdict
pathdict.Store("/css", true)
pathdict.Store("/fonts", true)
pathdict.Store("/img", true)
@ -39,7 +43,7 @@ func main() {
pathdict.Store("/svg", true)
pathdict.Store("/favicon.ico", true)
rootDir := "../server" // Change this to your root directory
rootDir := "../server" // 更改为你的根目录
vueBuild := "/opt/fusenpack-vue-created"
apiURL, err := url.Parse("http://localhost:9900")
if err != nil {
@ -48,6 +52,7 @@ func main() {
mux := http.NewServeMux()
// 获取并解析服务信息
results := GetZeroInfo(rootDir)
var allRoutes map[string]bool = make(map[string]bool)
@ -59,20 +64,23 @@ func main() {
allRoutes[k] = true
}
// 根据获取的服务信息创建后端服务
Backends = append(Backends,
NewBackend(mux,
fmt.Sprintf("http://%s:%d", result.Host, result.Port),
routes...))
}
// Define the static file server that serves the Vue dist folder
// 定义用于服务Vue dist文件夹的静态文件服务器
fs := http.FileServer(http.Dir(vueBuild))
indexHtmlPath := vueBuild + "/index.html"
mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/api") {
// 对/api开头的请求进行反向代理
proxy := httputil.NewSingleHostReverseProxy(apiURL)
proxy.ServeHTTP(w, r)
} else {
// 根据请求路径判断是服务静态文件或者是返回index.html
idx := strings.Index(r.URL.Path[1:], "/")
var prefix string
if idx != -1 {
@ -95,6 +103,7 @@ func main() {
log.Fatal(http.ListenAndServe(ServerAddress, mux))
}
// 后端服务的类型
type Backend struct {
HttpAddress string
Client *http.Client
@ -102,7 +111,7 @@ type Backend struct {
}
func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Backend {
// 如果路径最后没有以'/'结尾,则添加'/'
for i, muxPath := range muxPaths {
if muxPath[len(muxPath)-1] != '/' {
muxPath = muxPath + "/"
@ -110,6 +119,7 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
}
}
// 创建HTTP客户端设置相关的超时参数和连接数限制
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
@ -125,23 +135,22 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
},
}
// 创建后端服务对象,包含地址和客户端
backend := &Backend{
HttpAddress: httpAddress,
Client: client,
}
// 创建处理请求的函数
handleRequest := func(w http.ResponseWriter, r *http.Request) {
// 解析目标URL包含了查询参数
targetURL, err := url.Parse(httpAddress + r.URL.Path)
if err != nil {
http.Error(w, "Error parsing target URL", http.StatusInternalServerError)
return
}
// hasBridge := strings.Contains(r.Header.Get("Access-Control-Request-Headers"), "bridge")
// 解析目标URL时已经包含了查询参数
targetURL.RawQuery = r.URL.RawQuery
// 创建新的请求
proxyReq, err := http.NewRequest(r.Method, targetURL.String(), r.Body)
if err != nil {
http.Error(w, "Error creating proxy request", http.StatusInternalServerError)
@ -159,6 +168,7 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
proxyReq.ContentLength = r.ContentLength
proxyReq.Header.Set("Content-Type", r.Header.Get("Content-Type"))
// 发送请求
resp, err := backend.Client.Do(proxyReq)
if err != nil {
http.Error(w, "Error sending proxy request", http.StatusInternalServerError)
@ -173,10 +183,6 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
}
}
// if hasBridge {
// w.Header().Add("Access-Control-Allow-Headers", "Bridge")
// }
// 转发目标服务器的响应状态码和主体
w.WriteHeader(resp.StatusCode)
_, err = io.Copy(w, resp.Body)
@ -186,9 +192,11 @@ func NewBackend(mux *http.ServeMux, httpAddress string, muxPaths ...string) *Bac
}
}
// 为每个路径注册处理函数
for _, muxPath := range muxPaths {
mux.HandleFunc(muxPath, handleRequest)
}
// 返回后端服务对象
return backend
}

View File

@ -8,5 +8,13 @@ Auth:
AccessExpire: 2592000
RefreshAfter: 1592000
OAuth:
- name: google
appid: 1064842923358-e94msq2glj6qr4lrva9ts3q8h.apps.googleusercontent.com
secret: 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
- name: facebook
appid: 1095953604597065
secret: b146872550a190d5275b1420c212002e
Stripe:
SK: "sk_test_51IisojHygnIJZeghPVSBhkwySfcyDV4SoAduIxu3J7bvSJ9cZMD96LY1LO6SpdbYquLJX5oKvgEBB67KT9pecfCy00iEC4pp9y"
SK: sk_test_51IisojHygnIJZeghPVSBhkwySfcyDV4SoAduIxu3J7bvSJ9cZMD96LY1LO6SpdbYquLJX5oKvgEBB67KT9pecfCy00iEC4pp9y

View File

@ -6,11 +6,19 @@ import (
"github.com/zeromicro/go-zero/rest"
)
type OAuth struct {
Name string `json:"name"`
Appid string `json:"appid"`
Secret string `json:"secret"`
}
type Config struct {
rest.RestConf
SourceMysql string
Auth types.Auth
OAuth []OAuth
Stripe struct {
SK string
}

View File

@ -67,6 +67,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/api/user/order-delete",
Handler: UserOderDeleteHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/user/oauth2/login/google",
Handler: UserGoogleLoginHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/user/oauth2/login",
Handler: UserOAuth2LoginHandler(serverCtx),
},
},
)
}

View File

@ -0,0 +1,78 @@
package handler
import (
"errors"
"net/http"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/server/home-user-auth/internal/logic"
"fusenapi/server/home-user-auth/internal/svc"
"fusenapi/server/home-user-auth/internal/types"
)
func UserGoogleLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.RequestGoogleLogin
// 如果端点有请求结构体则使用httpx.Parse方法从HTTP请求体中解析请求数据
if err := httpx.Parse(r, &req); err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 510,
Message: "parameter error",
})
logx.Info(err)
return
}
// 创建一个业务逻辑层实例
l := logic.NewUserGoogleLoginLogic(r.Context(), svcCtx)
resp := l.UserGoogleLogin(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {
err := errors.New("server logic is error, resp must not be nil")
httpx.ErrorCtx(r.Context(), w, err)
logx.Error(err)
}
}
}

View File

@ -0,0 +1,78 @@
package handler
import (
"errors"
"net/http"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/server/home-user-auth/internal/logic"
"fusenapi/server/home-user-auth/internal/svc"
"fusenapi/server/home-user-auth/internal/types"
)
func UserOAuth2LoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.RequestOAuth
// 如果端点有请求结构体则使用httpx.Parse方法从HTTP请求体中解析请求数据
if err := httpx.Parse(r, &req); err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 510,
Message: "parameter error",
})
logx.Info(err)
return
}
// 创建一个业务逻辑层实例
l := logic.NewUserOAuth2LoginLogic(r.Context(), svcCtx)
resp := l.UserOAuth2Login(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {
err := errors.New("server logic is error, resp must not be nil")
httpx.ErrorCtx(r.Context(), w, err)
logx.Error(err)
}
}
}

View File

@ -0,0 +1,34 @@
package logic
import (
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"context"
"fusenapi/server/home-user-auth/internal/svc"
"fusenapi/server/home-user-auth/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type UserGoogleLoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewUserGoogleLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserGoogleLoginLogic {
return &UserGoogleLoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *UserGoogleLoginLogic) UserGoogleLogin(req *types.RequestGoogleLogin, userinfo *auth.UserInfo) (resp *basic.Response) {
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
// userinfo 传入值时, 一定不为null
return resp.SetStatus(basic.CodeOK)
}

View File

@ -0,0 +1,64 @@
package logic
import (
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"log"
"context"
"fusenapi/server/home-user-auth/internal/svc"
"fusenapi/server/home-user-auth/internal/types"
"github.com/474420502/requests"
"github.com/zeromicro/go-zero/core/logx"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
type UserOAuth2LoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewUserOAuth2LoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserOAuth2LoginLogic {
return &UserOAuth2LoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *UserOAuth2LoginLogic) UserOAuth2Login(req *types.RequestOAuth, userinfo *auth.UserInfo) (resp *basic.Response) {
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
// userinfo 传入值时, 一定不为null
switch req.Platform {
case "google":
var googleOauthConfig = &oauth2.Config{
RedirectURL: "https://fusenh5.kayue.cn/api/user/oauth2/login/google",
ClientID: l.svcCtx.Config.OAuth[0].Appid,
ClientSecret: l.svcCtx.Config.OAuth[0].Secret,
Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"},
Endpoint: google.Endpoint,
}
token, err := googleOauthConfig.Exchange(context.Background(), req.Code)
if err != nil {
resp.SetStatus(basic.CodeApiErr)
}
resp, err := requests.Get("https://www.googleapis.com/oauth2/v2/userinfo" + token.AccessToken).Execute()
if err != nil {
panic(err)
}
log.Println(resp.Json())
case "facebook":
default:
}
return resp.SetStatus(basic.CodeOK)
}

View File

@ -5,6 +5,24 @@ import (
"fusenapi/utils/basic"
)
type RequestGoogleLogin struct {
ID string `json:"id,,optional"`
Email string `json:"email,,optional"`
VerifiedEmail bool `json:"verified_email,,optional"`
Name string `json:"name,,optional"`
GivenName string `json:"given_name,,optional"`
FamilyName string `json:"family_name,,optional"`
Link string `json:"link,,optional"`
Picture string `json:"picture,,optional"`
Gender string `json:"gender,,optional"`
Locale string `json:"locale,,optional"`
}
type RequestOAuth struct {
Platform string `json:"platform"`
Code string `json:"code"`
}
type RequestContactService struct {
Type string `json:"type"` // 类型
RelationID int64 `json:"relation_id"` // 关系id

View File

@ -10,10 +10,10 @@ info (
import "basic.api"
service home-user-auth {
@handler UserRegisterHandler
post /api/user/register(RequestUserRegister) returns (response);
// @handler UserRegisterHandler
// post /api/user/register(RequestUserRegister) returns (response);
@handler UserLoginHandler
post /api/user/login(RequestUserLogin) returns (response);
@ -49,6 +49,31 @@ service home-user-auth {
@handler UserOderDeleteHandler
post /api/user/order-delete(RequestOrderId) returns (response);
@handler UserGoogleLoginHandler
post /api/user/oauth2/login/google(RequestGoogleLogin) returns (response);
@handler UserOAuth2LoginHandler
post /api/user/oauth2/login(RequestOAuth) returns (response);
}
type RequestGoogleLogin {
ID string `json:"id,,optional"`
Email string `json:"email,,optional"`
VerifiedEmail bool `json:"verified_email,,optional"`
Name string `json:"name,,optional"`
GivenName string `json:"given_name,,optional"`
FamilyName string `json:"family_name,,optional"`
Link string `json:"link,,optional"`
Picture string `json:"picture,,optional"`
Gender string `json:"gender,,optional"`
Locale string `json:"locale,,optional"`
}
type RequestOAuth {
Platform string `json:"platform"`
Code string `json:"code"`
}
type RequestContactService {