main
workabee 8 months ago
parent 5342989d8c
commit 394e3ba4b1

4
.gitmodules vendored

@ -0,0 +1,4 @@
[submodule "exhibition-register"]
path = exhibition-register
url = http://192.168.12.3:3000/exhibition/exhibition-register.git
branch = main

@ -0,0 +1,22 @@
FROM testhub.szjixun.cn:9043/public/golang:1.18-alpine AS builder
LABEL stage=gobuilder
ENV CGO_ENABLED 0
ENV GOPROXY https://goproxy.cn,direct
WORKDIR /build
COPY exhibition-register-server /app/exhibition-register-server
#FROM 172.16.100.99:9006/alpine
#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
#RUN apk update --no-cache
#RUN apk add --no-cache ca-certificates
#RUN apk add --no-cache tzdata
FROM testhub.szjixun.cn:9043/public/self-alpine
COPY ./conf /app/conf
ENV TZ Asia/Shanghai
ENV MODE_ENV prod
WORKDIR /app
COPY --from=builder /app/exhibition-register-server .
EXPOSE 20301
CMD ["/app/exhibition-register-server"]

@ -0,0 +1,16 @@
FROM busybox:glibc
COPY ./conf/Shanghai /usr/share/zoneinfo/Asia/Shanghai
COPY ./conf/certs /etc/ssl/certs
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
#ENV TZ Asia/Shanghai
WORKDIR /app/main-client
#通过名称引用
COPY ./build/app ./bin/mainServer
COPY ./conf/ /app/conf/
COPY ./conf/ ./conf/
COPY ./conf/ /app/main-client/bin/conf/
WORKDIR /app/main-client/bin
CMD ["./mainServer"]

@ -0,0 +1,22 @@
FROM testhub.szjixun.cn:9043/public/golang:1.18-alpine AS builder
LABEL stage=gobuilder
ENV CGO_ENABLED 0
ENV GOPROXY https://goproxy.cn,direct
WORKDIR /build
COPY exhibition-register-server /app/exhibition-register-server
#FROM 172.16.100.99:9006/alpine
#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
#RUN apk update --no-cache
#RUN apk add --no-cache ca-certificates
#RUN apk add --no-cache tzdata
FROM testhub.szjixun.cn:9043/public/self-alpine
COPY ./conf /app/conf
ENV TZ Asia/Shanghai
ENV MODE_ENV k8stest
WORKDIR /app
COPY --from=builder /app/exhibition-register-server .
EXPOSE 20301
CMD ["/app/exhibition-register-server"]

@ -0,0 +1,2 @@
ls pb/exhibition/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}';

@ -0,0 +1,48 @@
package main
import (
_ "dubbo.apache.org/dubbo-go/v3/filter/tps/strategy"
_ "dubbo.apache.org/dubbo-go/v3/imports"
_ "exhibition-register/internal/handler"
"exhibition-register/pkg/app"
"exhibition-register/pkg/tracing"
"github.com/bwmarrin/snowflake"
"go.uber.org/zap"
"gorm.io/gorm"
)
func NewApp(Lg *zap.Logger, JaegerTracer *tracing.JaegerProvider, SfNode *snowflake.Node, ExhibitionRegister *gorm.DB) *app.App {
return &app.App{
Lg: Lg,
JaegerTracer: JaegerTracer,
SfNode: SfNode,
ExhibitionRegister: ExhibitionRegister,
}
}
//func main() {
// var err error
// exhibitionConfig.GetOptions()
// app.ModuleClients, err = InitApp()
// if err != nil {
// panic(err)
// }
//
// //l, err := net.Listen("tcp", ":8883")
// //if err != nil {
// // fmt.Printf("failed to listen: %v", err)
// // return
// //}
// //
// //s := grpc.NewServer() // 创建gRPC服务器
// //dci.RegisterDciServer(s, &controller.DciProvider{}) // 在gRPC服务端注册服务
// // 启动服务
// //err = s.Serve(l)
// //注册服务
// config.SetProviderService(&controller.ExamProvider{})
// common.Init()
// if err = config.Load(); err != nil {
// panic(err)
// }
// select {}
//}

@ -0,0 +1,19 @@
// go:build wireinject
//go:build wireinject
// +build wireinject
package main
import (
"exhibition-register/pkg/app"
"exhibition-register/pkg/db"
"exhibition-register/pkg/logger"
"exhibition-register/pkg/snowf"
"exhibition-register/pkg/tracing"
"github.com/google/wire"
)
func InitApp() (*app.App, error) {
wire.Build(logger.Provider, tracing.Provider, snowf.Provider, db.Provider, NewApp)
return &app.App{}, nil
}

@ -0,0 +1,27 @@
system:
mode: dev #正式 prod #测试 test # 开发 dev
config_source: config
exhibitionRegister:
host: 121.229.45.214
port: 9007
user: artuser
password: C250PflXIWv2SQm8
db_name: "exhibition_register"
zapLog:
level: "info"
filename: "logs/exhibition_register.log"
max_size: 5
max_age: 30
max_backups: 30
snowflake:
node_num: 4
start_time: "2024-01-29"
jaeger:
addr: "127.0.0.1:6831"
open: false
#rabbitmq:
# user: "myuser"
# password: "mypass"
# host: "localhost"
# port: 5672
# vhost: "oa"

@ -15,7 +15,7 @@ zapLog:
max_backups: 30
snowflake:
node_num: 4
start_time: "2023-12-20"
start_time: "2024-01-29"
jaeger:
addr: "127.0.0.1:6831"
open: false

@ -0,0 +1,69 @@
dubbo:
metrics:
enable: true # default is true
path: /metrics # default is /metrics
port: 9092 # default is 9090
namespace: dubboExhibition # default is dubbo 作为数据上报 metrics 的前缀
registries:
demoZK:
protocol: zookeeper
timeout: 10s
address: 127.0.0.1:2181 #本地
# address: 114.218.158.24:2181 #测试环境
protocols:
triple: #triple
name: tri
port: 21501
provider:
filter: tracing
services:
ExhibitionProvider:
interface: com.fontree.microservices.common.Exhibition
retries: 0
filter: tps,tracing
tps.limiter: method-service
tps.limit.strategy: fixedWindow
tps.limit.rejected.handler: DefaultValueHandler
tps.limit.interval: 1000 # 间隔时间
tps.limit.rate: 30 # 间隔时间内次数
warmup: 100 #预热时间
logger:
zap-config:
level: info # 日志级别
development: false
disableCaller: false
disableStacktrace: false
encoding: "json"
# zap encoder 配置
encoderConfig:
messageKey: "message"
levelKey: "level"
timeKey: "time"
nameKey: "logger"
callerKey: "caller"
stacktraceKey: "stacktrace"
lineEnding: ""
levelEncoder: "capitalColor"
timeEncoder: "iso8601"
durationEncoder: "seconds"
callerEncoder: "short"
nameEncoder: ""
EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"),
EncodeDuration: zapcore.SecondsDurationEncoder,
outputPaths:
- "stderr"
errorOutputPaths:
- "stderr"
lumberjack-config:
# 写日志的文件名称
filename: "runtime/logs/exhibition_register.log"
# 每个日志文件长度的最大大小,单位是 MiB。默认 100MiB
maxSize: 5
# 日志保留的最大天数(只保留最近多少天的日志)
maxAge: 30
# 只保留最近多少个日志文件,用于控制程序总日志的大小
maxBackups: 30
# 是否使用本地时间,默认使用 UTC 时间
localTime: true
# 是否压缩日志文件,压缩方法 gzip
compress: false

@ -19,7 +19,7 @@ zapLog:
max_backups: 30
snowflake:
node_num: 4
start_time: "2023-12-20"
start_time: "2024-01-29"
jaeger:
addr: "127.0.0.1:6831"
open: false

@ -19,7 +19,7 @@ zapLog:
max_backups: 30
snowflake:
node_num: 4
start_time: "2023-12-20"
start_time: "2024-01-29"
jaeger:
addr: "127.0.0.1:6831"
open: false

@ -19,7 +19,7 @@ zapLog:
max_backups: 30
snowflake:
node_num: 4
start_time: "2023-12-20"
start_time: "2024-01-29"
jaeger:
addr: "127.0.0.1:6831"
open: false

@ -0,0 +1,152 @@
package config
import (
"dubbo.apache.org/dubbo-go/v3/common/constant"
"exhibition-register/pkg/msg"
"fmt"
"github.com/spf13/viper"
"os"
"reflect"
"strings"
)
var Data = new(AppConfig)
type AppConfig struct {
System struct {
Mode string
ConfigSource string `mapstructure:"config_source"`
}
ExhibitionRegister struct {
Host string
Port string
User string
Password string
DbName string `mapstructure:"db_name"`
}
Redis struct {
DB string
Addr string
Password string
}
ZapLog struct {
Level string `mapstructure:"level"`
Filename string `mapstructure:"filename"`
MaxSize string `mapstructure:"max_size"`
MaxAge string `mapstructure:"max_age"`
MaxBackups string `mapstructure:"max_backups"`
}
SnowFlake struct {
NodeNum string `mapstructure:"node_num"`
StartTime string `mapstructure:"start_time"`
}
Jaeger struct {
Addr string `mapstructure:"host"`
Open string `mapstructure:"open"`
}
RabbitMq struct {
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
Host string `mapstructure:"host"`
Port string `mapstructure:"port"`
Vhost string `mapstructure:"vhost"`
}
}
func GetConf() (iniConf string, err error) {
if os.Getenv(msg.MODE_ENV) != "" {
if err = os.Setenv(constant.ConfigFileEnvKey, fmt.Sprintf("./conf/%s/%s", os.Getenv(msg.MODE_ENV), msg.SERVER_DUBBOGO_CONFIG)); err != nil {
return
}
}
if os.Getenv(msg.MODE_ENV) == "" {
iniConf = fmt.Sprintf("./conf/%s", msg.SERVER_CONFIG)
} else {
iniConf = fmt.Sprintf("./conf/%s/%s", os.Getenv(msg.MODE_ENV), msg.SERVER_CONFIG)
}
return
}
func GetOptions() {
iniConf, err := GetConf()
if err != nil {
panic("GetOptions err" + err.Error())
}
if err = Viper(iniConf); err != nil {
return
}
}
func Viper(iniConf string) (err error) {
viper.SetConfigFile(iniConf)
err = viper.ReadInConfig()
if err != nil {
panic("viper.ReadInConfig failed" + err.Error())
return
}
if err = viper.Unmarshal(Data); err != nil {
panic("viper.Unmarshal failed" + err.Error())
return
}
// 如果是configmap模式再修改
fmt.Println(Data.System)
if Data.System.ConfigSource == "configmap" {
traverseFields(reflect.ValueOf(*Data), "", Data)
}
return
}
func traverseFields(value reflect.Value, prefix string, configPtr interface{}) {
valueType := value.Type()
prefixEnv := "${"
suffixEnv := "}"
// 遍历结构体的字段
for i := 0; i < valueType.NumField(); i++ {
field := valueType.Field(i)
fieldValue := value.Field(i)
// 拼接字段名(带有前缀)
fieldName := prefix + field.Name
// 判断字段的类型
if fieldValue.Kind() == reflect.Struct {
// 递归遍历嵌套结构体字段
traverseFields(fieldValue, fieldName+".", configPtr)
} else {
// 获取字段的值
fieldValueStr := fmt.Sprintf("%v", fieldValue.Interface())
// 判断是不是需要通过环境变量获取
if len(fieldValueStr) > 3 && strings.HasPrefix(fieldValueStr, prefixEnv) && strings.HasSuffix(fieldValueStr, suffixEnv) {
end := len(fieldValueStr) - len(suffixEnv)
var hasDefault bool
if strings.Index(fieldValueStr, "|") > 0 {
hasDefault = true
end = strings.Index(fieldValueStr, "|")
}
envStr := fieldValueStr[len(prefixEnv):end]
getValue := os.Getenv(envStr)
if getValue == "" && hasDefault {
getValue = fieldValueStr[end+1 : len(fieldValueStr)-len(suffixEnv)]
}
setSubFieldValue(configPtr, fieldName, getValue)
}
}
}
}
func setSubFieldValue(configPtr interface{}, fieldPath string, newValue interface{}) {
value := reflect.ValueOf(configPtr).Elem()
fields := strings.Split(fieldPath, ".")
for _, field := range fields {
value = value.FieldByName(field)
if !value.IsValid() {
return // 字段不存在,直接返回
}
if value.Kind() == reflect.Ptr {
value = value.Elem() // 解引用指针类型的字段
}
}
// 检查字段是否可设置
if value.CanSet() {
// 根据字段类型,将新值转换为对应类型并设置字段的值
newValue := reflect.ValueOf(newValue).Convert(value.Type())
value.Set(newValue)
}
}

157
go.mod

@ -0,0 +1,157 @@
module exhibition-register
go 1.18
require (
dubbo.apache.org/dubbo-go/v3 v3.0.5
github.com/bwmarrin/snowflake v0.3.0
github.com/gin-gonic/gin v1.9.1
github.com/go-redis/redis v6.15.9+incompatible
github.com/google/wire v0.5.0
github.com/nacos-group/nacos-sdk-go v1.1.4
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/opentracing/opentracing-go v1.2.0
github.com/spf13/viper v1.17.0
github.com/streadway/amqp v1.1.0
github.com/uber/jaeger-client-go v2.30.0+incompatible
go.uber.org/zap v1.26.0
gorm.io/driver/mysql v1.5.2
gorm.io/gorm v1.25.5
)
require (
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
contrib.go.opencensus.io/exporter/prometheus v0.4.1 // indirect
github.com/RoaringBitmap/roaring v1.2.3 // indirect
github.com/Workiva/go-datastructures v1.0.52 // indirect
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect
github.com/alibaba/sentinel-golang v1.0.4 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 // indirect
github.com/apache/dubbo-getty v1.4.9-0.20221022181821-4dc6252ce98c // indirect
github.com/apache/dubbo-go-hessian2 v1.11.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/creasty/defaults v1.5.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5 // indirect
github.com/dubbogo/gost v1.13.2 // indirect
github.com/dubbogo/grpc-go v1.42.10 // indirect
github.com/dubbogo/triple v1.2.2-rc2 // indirect
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
github.com/envoyproxy/go-control-plane v0.11.1 // indirect
github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-co-op/gocron v1.9.0 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-kit/log v0.1.0 // indirect
github.com/go-logfmt/logfmt v0.5.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/go-resty/resty/v2 v2.7.0 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/vault/sdk v0.7.0 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/pp v3.0.1+incompatible // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/knadh/koanf v1.5.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect
github.com/pelletier/go-toml v1.7.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/polarismesh/polaris-go v1.3.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/prometheus/statsd_exporter v0.21.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shirou/gopsutil/v3 v3.22.2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.etcd.io/etcd/api/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/v3 v3.5.9 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.11.0 // indirect
go.opentelemetry.io/otel/trace v1.11.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/grpc v1.58.2 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

1474
go.sum

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
package controller

@ -0,0 +1,57 @@
package handler
import (
"errors"
"sync"
"dubbo.apache.org/dubbo-go/v3/common"
"dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/filter"
"dubbo.apache.org/dubbo-go/v3/protocol"
)
func init() {
extension.SetRejectedExecutionHandler("DefaultValueHandler", GetDefaultValueRejectedExecutionHandlerSingleton)
}
type DefaultValueRejectedExecutionHandler struct {
defaultResult sync.Map
}
func (mh *DefaultValueRejectedExecutionHandler) RejectedExecution(url *common.URL, invocation protocol.Invocation) protocol.Result {
key := url.ServiceKey() + "#" + invocation.MethodName()
result, loaded := mh.defaultResult.Load(key)
if !loaded {
// we didn't configure any default value for this invocation
return &protocol.RPCResult{
Err: errors.New("请求太频繁"),
}
}
return result.(*protocol.RPCResult)
}
func GetCustomRejectedExecutionHandler() filter.RejectedExecutionHandler {
return &DefaultValueRejectedExecutionHandler{}
}
var (
customHandlerOnce sync.Once
customHandlerInstance *DefaultValueRejectedExecutionHandler
)
/**
* the better way is designing the RejectedExecutionHandler as singleton.
*/
func GetDefaultValueRejectedExecutionHandlerSingleton() filter.RejectedExecutionHandler {
customHandlerOnce.Do(func() {
customHandlerInstance = &DefaultValueRejectedExecutionHandler{}
})
initDefaultValue()
return customHandlerInstance
}
func initDefaultValue() {
// setting your default value
}

@ -0,0 +1,923 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// The messages in this file describe the definitions found in .proto files.
// A valid .proto file can be translated directly to a FileDescriptorProto
// without any other information (e.g. without reading its imports).
syntax = "proto2";
package google.protobuf;
option go_package = "google.golang.org/protobuf/types/descriptorpb";
option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.Protobuf.Reflection";
option objc_class_prefix = "GPB";
option cc_enable_arenas = true;
// descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping.
option optimize_for = SPEED;
// The protocol compiler can output a FileDescriptorSet containing the .proto
// files it parses.
message FileDescriptorSet {
repeated FileDescriptorProto file = 1;
}
// Describes a complete .proto file.
message FileDescriptorProto {
optional string name = 1; // file name, relative to root of source tree
optional string package = 2; // e.g. "foo", "foo.bar", etc.
// Names of files imported by this file.
repeated string dependency = 3;
// Indexes of the public imported files in the dependency list above.
repeated int32 public_dependency = 10;
// Indexes of the weak imported files in the dependency list.
// For Google-internal migration only. Do not use.
repeated int32 weak_dependency = 11;
// All top-level definitions in this file.
repeated DescriptorProto message_type = 4;
repeated EnumDescriptorProto enum_type = 5;
repeated ServiceDescriptorProto service = 6;
repeated FieldDescriptorProto extension = 7;
optional FileOptions options = 8;
// This field contains optional information about the original source code.
// You may safely remove this entire field without harming runtime
// functionality of the descriptors -- the information is needed only by
// development tools.
optional SourceCodeInfo source_code_info = 9;
// The syntax of the proto file.
// The supported values are "proto2", "proto3", and "editions".
//
// If `edition` is present, this value must be "editions".
optional string syntax = 12;
// The edition of the proto file, which is an opaque string.
optional string edition = 13;
}
// Describes a message type.
message DescriptorProto {
optional string name = 1;
repeated FieldDescriptorProto field = 2;
repeated FieldDescriptorProto extension = 6;
repeated DescriptorProto nested_type = 3;
repeated EnumDescriptorProto enum_type = 4;
message ExtensionRange {
optional int32 start = 1; // Inclusive.
optional int32 end = 2; // Exclusive.
optional ExtensionRangeOptions options = 3;
}
repeated ExtensionRange extension_range = 5;
repeated OneofDescriptorProto oneof_decl = 8;
optional MessageOptions options = 7;
// Range of reserved tag numbers. Reserved tag numbers may not be used by
// fields or extension ranges in the same message. Reserved ranges may
// not overlap.
message ReservedRange {
optional int32 start = 1; // Inclusive.
optional int32 end = 2; // Exclusive.
}
repeated ReservedRange reserved_range = 9;
// Reserved field names, which may not be used by fields in the same message.
// A given name may only be reserved once.
repeated string reserved_name = 10;
}
message ExtensionRangeOptions {
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
// Describes a field within a message.
message FieldDescriptorProto {
enum Type {
// 0 is reserved for errors.
// Order is weird for historical reasons.
TYPE_DOUBLE = 1;
TYPE_FLOAT = 2;
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
// negative values are likely.
TYPE_INT64 = 3;
TYPE_UINT64 = 4;
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
// negative values are likely.
TYPE_INT32 = 5;
TYPE_FIXED64 = 6;
TYPE_FIXED32 = 7;
TYPE_BOOL = 8;
TYPE_STRING = 9;
// Tag-delimited aggregate.
// Group type is deprecated and not supported in proto3. However, Proto3
// implementations should still be able to parse the group wire format and
// treat group fields as unknown fields.
TYPE_GROUP = 10;
TYPE_MESSAGE = 11; // Length-delimited aggregate.
// New in version 2.
TYPE_BYTES = 12;
TYPE_UINT32 = 13;
TYPE_ENUM = 14;
TYPE_SFIXED32 = 15;
TYPE_SFIXED64 = 16;
TYPE_SINT32 = 17; // Uses ZigZag encoding.
TYPE_SINT64 = 18; // Uses ZigZag encoding.
}
enum Label {
// 0 is reserved for errors
LABEL_OPTIONAL = 1;
LABEL_REQUIRED = 2;
LABEL_REPEATED = 3;
}
optional string name = 1;
optional int32 number = 3;
optional Label label = 4;
// If type_name is set, this need not be set. If both this and type_name
// are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
optional Type type = 5;
// For message and enum types, this is the name of the type. If the name
// starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
// rules are used to find the type (i.e. first the nested types within this
// message are searched, then within the parent, on up to the root
// namespace).
optional string type_name = 6;
// For extensions, this is the name of the type being extended. It is
// resolved in the same manner as type_name.
optional string extendee = 2;
// For numeric types, contains the original text representation of the value.
// For booleans, "true" or "false".
// For strings, contains the default text contents (not escaped in any way).
// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
optional string default_value = 7;
// If set, gives the index of a oneof in the containing type's oneof_decl
// list. This field is a member of that oneof.
optional int32 oneof_index = 9;
// JSON name of this field. The value is set by protocol compiler. If the
// user has set a "json_name" option on this field, that option's value
// will be used. Otherwise, it's deduced from the field's name by converting
// it to camelCase.
optional string json_name = 10;
optional FieldOptions options = 8;
// If true, this is a proto3 "optional". When a proto3 field is optional, it
// tracks presence regardless of field type.
//
// When proto3_optional is true, this field must be belong to a oneof to
// signal to old proto3 clients that presence is tracked for this field. This
// oneof is known as a "synthetic" oneof, and this field must be its sole
// member (each proto3 optional field gets its own synthetic oneof). Synthetic
// oneofs exist in the descriptor only, and do not generate any API. Synthetic
// oneofs must be ordered after all "real" oneofs.
//
// For message fields, proto3_optional doesn't create any semantic change,
// since non-repeated message fields always track presence. However it still
// indicates the semantic detail of whether the user wrote "optional" or not.
// This can be useful for round-tripping the .proto file. For consistency we
// give message fields a synthetic oneof also, even though it is not required
// to track presence. This is especially important because the parser can't
// tell if a field is a message or an enum, so it must always create a
// synthetic oneof.
//
// Proto2 optional fields do not set this flag, because they already indicate
// optional with `LABEL_OPTIONAL`.
optional bool proto3_optional = 17;
}
// Describes a oneof.
message OneofDescriptorProto {
optional string name = 1;
optional OneofOptions options = 2;
}
// Describes an enum type.
message EnumDescriptorProto {
optional string name = 1;
repeated EnumValueDescriptorProto value = 2;
optional EnumOptions options = 3;
// Range of reserved numeric values. Reserved values may not be used by
// entries in the same enum. Reserved ranges may not overlap.
//
// Note that this is distinct from DescriptorProto.ReservedRange in that it
// is inclusive such that it can appropriately represent the entire int32
// domain.
message EnumReservedRange {
optional int32 start = 1; // Inclusive.
optional int32 end = 2; // Inclusive.
}
// Range of reserved numeric values. Reserved numeric values may not be used
// by enum values in the same enum declaration. Reserved ranges may not
// overlap.
repeated EnumReservedRange reserved_range = 4;
// Reserved enum value names, which may not be reused. A given name may only
// be reserved once.
repeated string reserved_name = 5;
}
// Describes a value within an enum.
message EnumValueDescriptorProto {
optional string name = 1;
optional int32 number = 2;
optional EnumValueOptions options = 3;
}
// Describes a service.
message ServiceDescriptorProto {
optional string name = 1;
repeated MethodDescriptorProto method = 2;
optional ServiceOptions options = 3;
}
// Describes a method of a service.
message MethodDescriptorProto {
optional string name = 1;
// Input and output type names. These are resolved in the same way as
// FieldDescriptorProto.type_name, but must refer to a message type.
optional string input_type = 2;
optional string output_type = 3;
optional MethodOptions options = 4;
// Identifies if client streams multiple client messages
optional bool client_streaming = 5 [default = false];
// Identifies if server streams multiple server messages
optional bool server_streaming = 6 [default = false];
}
// ===================================================================
// Options
// Each of the definitions above may have "options" attached. These are
// just annotations which may cause code to be generated slightly differently
// or may contain hints for code that manipulates protocol messages.
//
// Clients may define custom options as extensions of the *Options messages.
// These extensions may not yet be known at parsing time, so the parser cannot
// store the values in them. Instead it stores them in a field in the *Options
// message called uninterpreted_option. This field must have the same name
// across all *Options messages. We then use this field to populate the
// extensions when we build a descriptor, at which point all protos have been
// parsed and so all extensions are known.
//
// Extension numbers for custom options may be chosen as follows:
// * For options which will only be used within a single application or
// organization, or for experimental options, use field numbers 50000
// through 99999. It is up to you to ensure that you do not use the
// same number for multiple options.
// * For options which will be published and used publicly by multiple
// independent entities, e-mail protobuf-global-extension-registry@google.com
// to reserve extension numbers. Simply provide your project name (e.g.
// Objective-C plugin) and your project website (if available) -- there's no
// need to explain how you intend to use them. Usually you only need one
// extension number. You can declare multiple options with only one extension
// number by putting them in a sub-message. See the Custom Options section of
// the docs for examples:
// https://developers.google.com/protocol-buffers/docs/proto#options
// If this turns out to be popular, a web service will be set up
// to automatically assign option numbers.
message FileOptions {
// Sets the Java package where classes generated from this .proto will be
// placed. By default, the proto package is used, but this is often
// inappropriate because proto packages do not normally start with backwards
// domain names.
optional string java_package = 1;
// Controls the name of the wrapper Java class generated for the .proto file.
// That class will always contain the .proto file's getDescriptor() method as
// well as any top-level extensions defined in the .proto file.
// If java_multiple_files is disabled, then all the other classes from the
// .proto file will be nested inside the single wrapper outer class.
optional string java_outer_classname = 8;
// If enabled, then the Java code generator will generate a separate .java
// file for each top-level message, enum, and service defined in the .proto
// file. Thus, these types will *not* be nested inside the wrapper class
// named by java_outer_classname. However, the wrapper class will still be
// generated to contain the file's getDescriptor() method as well as any
// top-level extensions defined in the file.
optional bool java_multiple_files = 10 [default = false];
// This option does nothing.
optional bool java_generate_equals_and_hash = 20 [deprecated=true];
// If set true, then the Java2 code generator will generate code that
// throws an exception whenever an attempt is made to assign a non-UTF-8
// byte sequence to a string field.
// Message reflection will do the same.
// However, an extension field still accepts non-UTF-8 byte sequences.
// This option has no effect on when used with the lite runtime.
optional bool java_string_check_utf8 = 27 [default = false];
// Generated classes can be optimized for speed or code size.
enum OptimizeMode {
SPEED = 1; // Generate complete code for parsing, serialization,
// etc.
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
}
optional OptimizeMode optimize_for = 9 [default = SPEED];
// Sets the Go package where structs generated from this .proto will be
// placed. If omitted, the Go package will be derived from the following:
// - The basename of the package import path, if provided.
// - Otherwise, the package statement in the .proto file, if present.
// - Otherwise, the basename of the .proto file, without extension.
optional string go_package = 11;
// Should generic services be generated in each language? "Generic" services
// are not specific to any particular RPC system. They are generated by the
// main code generators in each language (without additional plugins).
// Generic services were the only kind of service generation supported by
// early versions of google.protobuf.
//
// Generic services are now considered deprecated in favor of using plugins
// that generate code specific to your particular RPC system. Therefore,
// these default to false. Old code which depends on generic services should
// explicitly set them to true.
optional bool cc_generic_services = 16 [default = false];
optional bool java_generic_services = 17 [default = false];
optional bool py_generic_services = 18 [default = false];
optional bool php_generic_services = 42 [default = false];
// Is this file deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for everything in the file, or it will be completely ignored; in the very
// least, this is a formalization for deprecating files.
optional bool deprecated = 23 [default = false];
// Enables the use of arenas for the proto messages in this file. This applies
// only to generated classes for C++.
optional bool cc_enable_arenas = 31 [default = true];
// Sets the objective c class prefix which is prepended to all objective c
// generated classes from this .proto. There is no default.
optional string objc_class_prefix = 36;
// Namespace for generated classes; defaults to the package.
optional string csharp_namespace = 37;
// By default Swift generators will take the proto package and CamelCase it
// replacing '.' with underscore and use that to prefix the types/symbols
// defined. When this options is provided, they will use this value instead
// to prefix the types/symbols defined.
optional string swift_prefix = 39;
// Sets the php class prefix which is prepended to all php generated classes
// from this .proto. Default is empty.
optional string php_class_prefix = 40;
// Use this option to change the namespace of php generated classes. Default
// is empty. When this option is empty, the package name will be used for
// determining the namespace.
optional string php_namespace = 41;
// Use this option to change the namespace of php generated metadata classes.
// Default is empty. When this option is empty, the proto file name will be
// used for determining the namespace.
optional string php_metadata_namespace = 44;
// Use this option to change the package of ruby generated classes. Default
// is empty. When this option is not set, the package name will be used for
// determining the ruby package.
optional string ruby_package = 45;
// The parser stores options it doesn't recognize here.
// See the documentation for the "Options" section above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message.
// See the documentation for the "Options" section above.
extensions 1000 to max;
reserved 38;
}
message MessageOptions {
// Set true to use the old proto1 MessageSet wire format for extensions.
// This is provided for backwards-compatibility with the MessageSet wire
// format. You should not use this for any other reason: It's less
// efficient, has fewer features, and is more complicated.
//
// The message must be defined exactly as follows:
// message Foo {
// option message_set_wire_format = true;
// extensions 4 to max;
// }
// Note that the message cannot have any defined fields; MessageSets only
// have extensions.
//
// All extensions of your type must be singular messages; e.g. they cannot
// be int32s, enums, or repeated messages.
//
// Because this is an option, the above two restrictions are not enforced by
// the protocol compiler.
optional bool message_set_wire_format = 1 [default = false];
// Disables the generation of the standard "descriptor()" accessor, which can
// conflict with a field of the same name. This is meant to make migration
// from proto1 easier; new code should avoid fields named "descriptor".
optional bool no_standard_descriptor_accessor = 2 [default = false];
// Is this message deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for the message, or it will be completely ignored; in the very least,
// this is a formalization for deprecating messages.
optional bool deprecated = 3 [default = false];
reserved 4, 5, 6;
// Whether the message is an automatically generated map entry type for the
// maps field.
//
// For maps fields:
// map<KeyType, ValueType> map_field = 1;
// The parsed descriptor looks like:
// message MapFieldEntry {
// option map_entry = true;
// optional KeyType key = 1;
// optional ValueType value = 2;
// }
// repeated MapFieldEntry map_field = 1;
//
// Implementations may choose not to generate the map_entry=true message, but
// use a native map in the target language to hold the keys and values.
// The reflection APIs in such implementations still need to work as
// if the field is a repeated message field.
//
// NOTE: Do not set the option in .proto files. Always use the maps syntax
// instead. The option should only be implicitly set by the proto compiler
// parser.
optional bool map_entry = 7;
reserved 8; // javalite_serializable
reserved 9; // javanano_as_lite
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message FieldOptions {
// The ctype option instructs the C++ code generator to use a different
// representation of the field than it normally would. See the specific
// options below. This option is not yet implemented in the open source
// release -- sorry, we'll try to include it in a future version!
optional CType ctype = 1 [default = STRING];
enum CType {
// Default mode.
STRING = 0;
CORD = 1;
STRING_PIECE = 2;
}
// The packed option can be enabled for repeated primitive fields to enable
// a more efficient representation on the wire. Rather than repeatedly
// writing the tag and type for each element, the entire array is encoded as
// a single length-delimited blob. In proto3, only explicit setting it to
// false will avoid using packed encoding.
optional bool packed = 2;
// The jstype option determines the JavaScript type used for values of the
// field. The option is permitted only for 64 bit integral and fixed types
// (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
// is represented as JavaScript string, which avoids loss of precision that
// can happen when a large value is converted to a floating point JavaScript.
// Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
// use the JavaScript "number" type. The behavior of the default option
// JS_NORMAL is implementation dependent.
//
// This option is an enum to permit additional types to be added, e.g.
// goog.math.Integer.
optional JSType jstype = 6 [default = JS_NORMAL];
enum JSType {
// Use the default type.
JS_NORMAL = 0;
// Use JavaScript strings.
JS_STRING = 1;
// Use JavaScript numbers.
JS_NUMBER = 2;
}
// Should this field be parsed lazily? Lazy applies only to message-type
// fields. It means that when the outer message is initially parsed, the
// inner message's contents will not be parsed but instead stored in encoded
// form. The inner message will actually be parsed when it is first accessed.
//
// This is only a hint. Implementations are free to choose whether to use
// eager or lazy parsing regardless of the value of this option. However,
// setting this option true suggests that the protocol author believes that
// using lazy parsing on this field is worth the additional bookkeeping
// overhead typically needed to implement it.
//
// This option does not affect the public interface of any generated code;
// all method signatures remain the same. Furthermore, thread-safety of the
// interface is not affected by this option; const methods remain safe to
// call from multiple threads concurrently, while non-const methods continue
// to require exclusive access.
//
//
// Note that implementations may choose not to check required fields within
// a lazy sub-message. That is, calling IsInitialized() on the outer message
// may return true even if the inner message has missing required fields.
// This is necessary because otherwise the inner message would have to be
// parsed in order to perform the check, defeating the purpose of lazy
// parsing. An implementation which chooses not to check required fields
// must be consistent about it. That is, for any particular sub-message, the
// implementation must either *always* check its required fields, or *never*
// check its required fields, regardless of whether or not the message has
// been parsed.
//
// As of May 2022, lazy verifies the contents of the byte stream during
// parsing. An invalid byte stream will cause the overall parsing to fail.
optional bool lazy = 5 [default = false];
// unverified_lazy does no correctness checks on the byte stream. This should
// only be used where lazy with verification is prohibitive for performance
// reasons.
optional bool unverified_lazy = 15 [default = false];
// Is this field deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for accessors, or it will be completely ignored; in the very least, this
// is a formalization for deprecating fields.
optional bool deprecated = 3 [default = false];
// For Google-internal migration only. Do not use.
optional bool weak = 10 [default = false];
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
reserved 4; // removed jtype
}
message OneofOptions {
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message EnumOptions {
// Set this option to true to allow mapping different tag names to the same
// value.
optional bool allow_alias = 2;
// Is this enum deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for the enum, or it will be completely ignored; in the very least, this
// is a formalization for deprecating enums.
optional bool deprecated = 3 [default = false];
reserved 5; // javanano_as_lite
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message EnumValueOptions {
// Is this enum value deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for the enum value, or it will be completely ignored; in the very least,
// this is a formalization for deprecating enum values.
optional bool deprecated = 1 [default = false];
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message ServiceOptions {
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
// framework. We apologize for hoarding these numbers to ourselves, but
// we were already using them long before we decided to release Protocol
// Buffers.
// Is this service deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for the service, or it will be completely ignored; in the very least,
// this is a formalization for deprecating services.
optional bool deprecated = 33 [default = false];
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
message MethodOptions {
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
// framework. We apologize for hoarding these numbers to ourselves, but
// we were already using them long before we decided to release Protocol
// Buffers.
// Is this method deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for the method, or it will be completely ignored; in the very least,
// this is a formalization for deprecating methods.
optional bool deprecated = 33 [default = false];
// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
// or neither? HTTP based RPC implementation may choose GET verb for safe
// methods, and PUT verb for idempotent methods instead of the default POST.
enum IdempotencyLevel {
IDEMPOTENCY_UNKNOWN = 0;
NO_SIDE_EFFECTS = 1; // implies idempotent
IDEMPOTENT = 2; // idempotent, but may have side effects
}
optional IdempotencyLevel idempotency_level = 34
[default = IDEMPOTENCY_UNKNOWN];
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
// Clients can define custom options in extensions of this message. See above.
extensions 1000 to max;
}
// A message representing a option the parser does not recognize. This only
// appears in options protos created by the compiler::Parser class.
// DescriptorPool resolves these when building Descriptor objects. Therefore,
// options protos in descriptor objects (e.g. returned by Descriptor::options(),
// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
// in them.
message UninterpretedOption {
// The name of the uninterpreted option. Each string represents a segment in
// a dot-separated name. is_extension is true iff a segment represents an
// extension (denoted with parentheses in options specs in .proto files).
// E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents
// "foo.(bar.baz).moo".
message NamePart {
required string name_part = 1;
required bool is_extension = 2;
}
repeated NamePart name = 2;
// The value of the uninterpreted option, in whatever type the tokenizer
// identified it as during parsing. Exactly one of these should be set.
optional string identifier_value = 3;
optional uint64 positive_int_value = 4;
optional int64 negative_int_value = 5;
optional double double_value = 6;
optional bytes string_value = 7;
optional string aggregate_value = 8;
}
// ===================================================================
// Optional source code info
// Encapsulates information about the original source file from which a
// FileDescriptorProto was generated.
message SourceCodeInfo {
// A Location identifies a piece of source code in a .proto file which
// corresponds to a particular definition. This information is intended
// to be useful to IDEs, code indexers, documentation generators, and similar
// tools.
//
// For example, say we have a file like:
// message Foo {
// optional string foo = 1;
// }
// Let's look at just the field definition:
// optional string foo = 1;
// ^ ^^ ^^ ^ ^^^
// a bc de f ghi
// We have the following locations:
// span path represents
// [a,i) [ 4, 0, 2, 0 ] The whole field definition.
// [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
// [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
// [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
// [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
//
// Notes:
// - A location may refer to a repeated field itself (i.e. not to any
// particular index within it). This is used whenever a set of elements are
// logically enclosed in a single code segment. For example, an entire
// extend block (possibly containing multiple extension definitions) will
// have an outer location whose path refers to the "extensions" repeated
// field without an index.
// - Multiple locations may have the same path. This happens when a single
// logical declaration is spread out across multiple places. The most
// obvious example is the "extend" block again -- there may be multiple
// extend blocks in the same scope, each of which will have the same path.
// - A location's span is not always a subset of its parent's span. For
// example, the "extendee" of an extension declaration appears at the
// beginning of the "extend" block and is shared by all extensions within
// the block.
// - Just because a location's span is a subset of some other location's span
// does not mean that it is a descendant. For example, a "group" defines
// both a type and a field in a single declaration. Thus, the locations
// corresponding to the type and field and their components will overlap.
// - Code which tries to interpret locations should probably be designed to
// ignore those that it doesn't understand, as more types of locations could
// be recorded in the future.
repeated Location location = 1;
message Location {
// Identifies which part of the FileDescriptorProto was defined at this
// location.
//
// Each element is a field number or an index. They form a path from
// the root FileDescriptorProto to the place where the definition occurs.
// For example, this path:
// [ 4, 3, 2, 7, 1 ]
// refers to:
// file.message_type(3) // 4, 3
// .field(7) // 2, 7
// .name() // 1
// This is because FileDescriptorProto.message_type has field number 4:
// repeated DescriptorProto message_type = 4;
// and DescriptorProto.field has field number 2:
// repeated FieldDescriptorProto field = 2;
// and FieldDescriptorProto.name has field number 1:
// optional string name = 1;
//
// Thus, the above path gives the location of a field name. If we removed
// the last element:
// [ 4, 3, 2, 7 ]
// this path refers to the whole field declaration (from the beginning
// of the label to the terminating semicolon).
repeated int32 path = 1 [packed = true];
// Always has exactly three or four elements: start line, start column,
// end line (optional, otherwise assumed same as start line), end column.
// These are packed into a single field for efficiency. Note that line
// and column numbers are zero-based -- typically you will want to add
// 1 to each before displaying to a user.
repeated int32 span = 2 [packed = true];
// If this SourceCodeInfo represents a complete declaration, these are any
// comments appearing before and after the declaration which appear to be
// attached to the declaration.
//
// A series of line comments appearing on consecutive lines, with no other
// tokens appearing on those lines, will be treated as a single comment.
//
// leading_detached_comments will keep paragraphs of comments that appear
// before (but not connected to) the current element. Each paragraph,
// separated by empty lines, will be one comment element in the repeated
// field.
//
// Only the comment content is provided; comment markers (e.g. //) are
// stripped out. For block comments, leading whitespace and an asterisk
// will be stripped from the beginning of each line other than the first.
// Newlines are included in the output.
//
// Examples:
//
// optional int32 foo = 1; // Comment attached to foo.
// // Comment attached to bar.
// optional int32 bar = 2;
//
// optional string baz = 3;
// // Comment attached to baz.
// // Another line attached to baz.
//
// // Comment attached to moo.
// //
// // Another line attached to moo.
// optional double moo = 4;
//
// // Detached comment for corge. This is not leading or trailing comments
// // to moo or corge because there are blank lines separating it from
// // both.
//
// // Detached comment for corge paragraph 2.
//
// optional string corge = 5;
// /* Block comment attached
// * to corge. Leading asterisks
// * will be removed. */
// /* Block comment attached to
// * grault. */
// optional int32 grault = 6;
//
// // ignored detached comments.
optional string leading_comments = 3;
optional string trailing_comments = 4;
repeated string leading_detached_comments = 6;
}
}
// Describes the relationship between generated code and its original source
// file. A GeneratedCodeInfo message is associated with only one generated
// source file, but may contain references to different source .proto files.
message GeneratedCodeInfo {
// An Annotation connects some span of text in generated code to an element
// of its generating .proto file.
repeated Annotation annotation = 1;
message Annotation {
// Identifies the element in the original source .proto file. This field
// is formatted the same as SourceCodeInfo.Location.path.
repeated int32 path = 1 [packed = true];
// Identifies the filesystem path to the original source .proto.
optional string source_file = 2;
// Identifies the starting offset in bytes in the generated code
// that relates to the identified object.
optional int32 begin = 3;
// Identifies the ending offset in bytes in the generated code that
// relates to the identified offset. The end offset should be one past
// the last relevant byte (so the length of the text = end - begin).
optional int32 end = 4;
}
}

@ -0,0 +1,11 @@
syntax = "proto3";
package exhibition;
option go_package = "./exhibition";
import "pb/descriptor.proto";
import "pb/validator.proto";
service Exhibition {
}

@ -0,0 +1,80 @@
// Copyright 2016 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.
// Protocol Buffers extensions for defining auto-generateable validators for messages.
// TODO(mwitkow): Add example.
syntax = "proto2";
package validator;
import "pb/descriptor.proto";
option go_package = "github.com/mwitkow/go-proto-validators;validator";
// TODO(mwitkow): Email protobuf-global-extension-registry@google.com to get an extension ID.
extend google.protobuf.FieldOptions {
optional FieldValidator field = 65020;
}
extend google.protobuf.OneofOptions {
optional OneofValidator oneof = 65021;
}
message FieldValidator {
// Uses a Golang RE2-syntax regex to match the field contents.
optional string regex = 1;
// Field value of integer strictly greater than this value.
optional int64 int_gt = 2;
// Field value of integer strictly smaller than this value.
optional int64 int_lt = 3;
// Used for nested message types, requires that the message type exists.
optional bool msg_exists = 4;
// Human error specifies a user-customizable error that is visible to the user.
optional string human_error = 5;
// Field value of double strictly greater than this value.
// Note that this value can only take on a valid floating point
// value. Use together with float_epsilon if you need something more specific.
optional double float_gt = 6;
// Field value of double strictly smaller than this value.
// Note that this value can only take on a valid floating point
// value. Use together with float_epsilon if you need something more specific.
optional double float_lt = 7;
// Field value of double describing the epsilon within which
// any comparison should be considered to be true. For example,
// when using float_gt = 0.35, using a float_epsilon of 0.05
// would mean that any value above 0.30 is acceptable. It can be
// thought of as a {float_value_condition} +- {float_epsilon}.
// If unset, no correction for floating point inaccuracies in
// comparisons will be attempted.
optional double float_epsilon = 8;
// Floating-point value compared to which the field content should be greater or equal.
optional double float_gte = 9;
// Floating-point value compared to which the field content should be smaller or equal.
optional double float_lte = 10;
// Used for string fields, requires the string to be not empty (i.e different from "").
optional bool string_not_empty = 11;
// Repeated field with at least this number of elements.
optional int64 repeated_count_min = 12;
// Repeated field with at most this number of elements.
optional int64 repeated_count_max = 13;
// Field value of length greater than this value.
optional int64 length_gt = 14;
// Field value of length smaller than this value.
optional int64 length_lt = 15;
// Field value of length strictly equal to this value.
optional int64 length_eq = 16;
// Requires that the value is in the enum.
optional bool is_in_enum = 17;
// Ensures that a string value is in UUID format.
// uuid_ver specifies the valid UUID versions. Valid values are: 0-5.
// If uuid_ver is 0 all UUID versions are accepted.
optional int32 uuid_ver = 18;
}
message OneofValidator {
// Require that one of the oneof fields is set.
optional bool required = 1;
}

@ -0,0 +1,20 @@
package amqp
import (
"github.com/google/wire"
"github.com/streadway/amqp"
)
var RabbitMqConn *amqp.Connection
var Provider = wire.NewSet(NewRabbitMq)
func NewRabbitMq() *amqp.Connection {
//var err error
// 创建连接
/*RabbitMqConn, err = amqp.Dial(fmt.Sprintf("amqp://%s:%s@%s:%d/%s", appConfig.Data.RabbitMq.User, appConfig.Data.RabbitMq.Password, appConfig.Data.RabbitMq.Host, appConfig.Data.RabbitMq.Port, appConfig.Data.RabbitMq.Vhost))
if err != nil {
log.Fatalf("failed to connect RabbitMQ: %v", err)
}*/
return RabbitMqConn
}

@ -0,0 +1,18 @@
package app
import (
"exhibition-register/pkg/tracing"
"github.com/bwmarrin/snowflake"
"go.uber.org/zap"
"gorm.io/gorm"
)
var ModuleClients *App
type App struct {
Lg *zap.Logger
//RedisClient *redis.Client
JaegerTracer *tracing.JaegerProvider
ExhibitionRegister *gorm.DB
SfNode *snowflake.Node
}

24
pkg/cache/redis.go vendored

@ -0,0 +1,24 @@
package cache
import (
"github.com/go-redis/redis"
"github.com/google/wire"
)
var RedisProvider = wire.NewSet(NewRedis)
// TODO 添加连接池
func NewRedis() *redis.Client {
//redisDb, _ := strconv.Atoi(dciConfig.Data.Redis.DB)
//RedisClient := redis.NewClient(&redis.Options{
// Addr: dciConfig.Data.Redis.Addr,
// Password: dciConfig.Data.Redis.Password,
// DB: redisDb,
//})
//_, err := RedisClient.Ping().Result()
//if err != nil {
// logger.Errorf("connRedis err", err)
// panic(err)
//}
return nil
}

@ -0,0 +1,18 @@
package db
import (
exhibitionConfig "exhibition-register/config"
"github.com/google/wire"
"gorm.io/gorm"
"strings"
)
var Provider = wire.NewSet(NewDB)
func NewDB() *gorm.DB {
connDci := strings.Join([]string{exhibitionConfig.Data.ExhibitionRegister.User, ":", exhibitionConfig.Data.ExhibitionRegister.Password,
"@tcp(", exhibitionConfig.Data.ExhibitionRegister.Host, ":", exhibitionConfig.Data.ExhibitionRegister.Port, ")/",
exhibitionConfig.Data.ExhibitionRegister.DbName, "?charset=utf8mb4&parseTime=true&loc=Local"}, "")
ExhibitionRegister := loadMysqlConn(connDci)
return ExhibitionRegister
}

@ -0,0 +1,62 @@
package db
import (
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
"time"
)
func loadMysqlConn(conn string) *gorm.DB {
var ormLogger logger.Interface
if gin.Mode() == "debug" {
ormLogger = logger.Default.LogMode(logger.Info)
} else {
ormLogger = logger.Default
}
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: conn, // DSN data source name
DefaultStringSize: 256, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据版本自动配置
}), &gorm.Config{
Logger: ormLogger,
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
DisableForeignKeyConstraintWhenMigrating: true,
})
if err != nil {
panic(err)
}
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(20) //设置连接池,空闲
sqlDB.SetMaxOpenConns(100) //打开
sqlDB.SetConnMaxLifetime(time.Second * 30)
err = db.AutoMigrate() //自迁移
if err != nil {
return nil
}
return db
}
func addColumn(db *gorm.DB, dst interface{}, column string) {
exist := db.Migrator().HasColumn(dst, column)
if !exist {
err := db.Migrator().AddColumn(dst, column)
if err != nil {
panic(err)
}
}
return
}
func addTable(db *gorm.DB, dst interface{}) {
return
}

@ -0,0 +1,28 @@
package err
import (
"errors"
"exhibition-register/pkg/app"
"fmt"
"go.uber.org/zap"
)
func ReturnError(err error, msg, print string) error {
if err != nil {
field := zap.Field{}
field.String = err.Error()
//app.ModuleClients.Lg.Error(print, field)
fmt.Printf(print+"%+v\n", err)
return errors.New(msg)
}
return nil
}
func NoReturnError(err error, print string) {
if err != nil {
field := zap.Field{}
field.String = err.Error()
app.ModuleClients.Lg.Error(print, field)
fmt.Printf(print+"%+v\n", err)
}
}

@ -0,0 +1,9 @@
package err
var ResultCode = map[string]string{
"OK": "正常返回",
"BAD_REQUEST": "请求参数错误",
"PERMISSION_ERROR": "权限错误",
"BUSINESS_ERROR": "业务内容错误",
"SERVER_ERROR": "服务器错误",
}

@ -0,0 +1,3 @@
package err
var ResultMsg = map[string]string{}

@ -0,0 +1,5 @@
package common
func Init() {
//db.DBMigration()
}

@ -0,0 +1,63 @@
package logger
import (
exhibitionConfig "exhibition-register/config"
"github.com/google/wire"
"os"
"strconv"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var Provider = wire.NewSet(ZapInit)
// ZapInit 初始化lg
func ZapInit() *zap.Logger {
var err error
maxSize, _ := strconv.Atoi(exhibitionConfig.Data.ZapLog.MaxSize)
maxAge, _ := strconv.Atoi(exhibitionConfig.Data.ZapLog.MaxAge)
maxBackups, _ := strconv.Atoi(exhibitionConfig.Data.ZapLog.MaxAge)
writeSyncer := getLogWriter(exhibitionConfig.Data.ZapLog.Filename, maxSize, maxBackups, maxAge)
encoder := getEncoder()
var l = new(zapcore.Level)
err = l.UnmarshalText([]byte(exhibitionConfig.Data.ZapLog.Level))
if err != nil {
return nil
}
var core zapcore.Core
if exhibitionConfig.Data.System.Mode == "dev" {
// 进入开发模式,日志输出到终端
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
core = zapcore.NewTee(
zapcore.NewCore(encoder, writeSyncer, l),
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), zapcore.DebugLevel),
)
} else {
core = zapcore.NewCore(encoder, writeSyncer, l)
}
lg := zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(lg)
return lg
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.TimeKey = "time"
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
return zapcore.NewJSONEncoder(encoderConfig)
}
func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: filename,
MaxSize: maxSize,
MaxBackups: maxBackup,
MaxAge: maxAge,
}
return zapcore.AddSync(lumberJackLogger)
}

@ -0,0 +1,122 @@
package msg
const (
SERVER_CONFIG = "config.yaml"
SERVER_DUBBOGO_CONFIG = "dubbogo.yaml"
MODE_ENV = "MODE_ENV"
)
const (
Success = "操作成功"
Failed = "操作失败"
)
const (
WholeTimeFormat = "2006-01-02 15:04:05"
)
const (
//ExamWaiting = 1 //未开始
ExamDoing = 1 //进行中
ExamFinished = 2 //已结束
TrainWaiting = 1 //未开始
TrainDoing = 2 //进行中
TrainFinished = 3 //已结束
IsRight = 1 //正确
IsErr = 2 //正确
IsPass = 3 // 通过
NotPass = 2 // 未通过
IsNotStart = 1 // 未完成
NotGot = 1
IsGot = 2
IsGift = 2
IsNotGift = 1
IsTrain = 1 // 完成培训 及 录制了视频
IsNeedAnswer = 1 // 需要答题
IsNeedTrain = 1 // 需要培训
IsAll = 1 // 全部都需要参加
)
const (
Http = 200
)
const (
ErrorLogin = "账号或密码错误"
ErrorJSONParse = "json解析失败"
ErrorJSONMarshal = "json序列化失败"
ErrorForUpdate = "锁定错误"
ErrorInsert = "插入异常"
ErrorDelete = "删除异常"
ErrorUpdate = "更新异常"
ErrorSelect = "查询异常"
ErrorEmptyParam = "值为空"
ErrorCopierStruct = "拷贝结构体错误"
ErrorNoAction = "无需操作"
ErrorInvalidParam = "参数不合法"
ErrorNoData = "没有数据"
ErrorDatetime = "时间格式错误"
ErrorSha256Write = "sha256加密错误"
)
const (
ErrOperate = "操作错误"
ErrCreateUser = "创建用户失败"
ErrUpdateUser = "更新用户失败"
ErrGetUserInfo = "查询用户信息失败"
ErrGetUserInfoExam = "查询答题用户信息失败"
ErrUserNotRegister = "用户未注册"
ErrVerifyUser = "校验用户信息失败"
ErrUserHad = "当前用户信息已存在"
ErrCreateExam = "创建考试失败"
ErrUpdateExam = "更新考试失败"
ErrGetExamInfoData = "查询考试信息失败"
ErrGetExamInfoCount = "查询考试信息失败"
ErrGetExamInfoNoParams = "查询考试信息条件错误"
ErUpdateExamStatus = "更新考试状态错误"
ErrCreateTrain = "创建培训失败"
ErrUpdateTrain = "更新培训失败"
ErrGetTrainInfoData = "查询培训信息失败"
ErrGetTrainInfoCount = "查询培训信息失败"
ErrGetTrainInfoNoParams = "查询培训信息条件错误"
ErrCreateQuestion = "创建题目失败"
ErrUpdateQuestion = "更新题目失败"
ErrQuestionInUse = "题目正在被使用,无法修改"
ErrGetQuestionInfoData = "查询题目信息失败"
ErrGetQuestionInfoCount = "查询题目信息失败"
ErrCreateGift = "创建礼品失败"
ErrUpdateGift = "更新礼品失败"
ErrGetGiftInfoData = "查询礼品信息失败"
ErrGetGiftInfoCount = "查询礼品信息失败"
ErrCreateUserHis = "创建考试成绩失败"
ErrQueryUserHis = "查询考试成绩失败"
ErrQueryAnswerScore = "查询答案分值失败"
ErrQueryAnswer = "查询答案失败"
ErrCreateUserAnswerHis = "创建作答记录失败"
ErrCreateUserTrainHis = "创建培训记录失败"
ErrUpdateUserTrainHis = "更新培训记录失败"
ErrCreateUserGiftHis = "创建礼品记录失败"
ErrUpdateUserGiftHis = "更新礼品状态失败"
ErrCheckAnswer = "答案核对失败"
ErrUpdateUserHis = "更新考试成绩失败"
ErrUpdateParticipantNum = "更新参与人数失败"
ErrUpdateParticipantPassNum = "更新通过人数失败"
ErrQueryVideo = "查询视频信息失败"
ErrQueryUserAnswerHis = "查询答题记录失败"
)

@ -0,0 +1,4 @@
package service
func init() {
}

@ -0,0 +1,36 @@
package snowf
import (
exhibitionConfig "exhibition-register/config"
"exhibition-register/pkg/app"
"github.com/bwmarrin/snowflake"
"github.com/google/wire"
"strconv"
"time"
)
var Provider = wire.NewSet(NewSf)
func NewSf() *snowflake.Node {
var err error
var st time.Time
nodeNum, _ := strconv.Atoi(exhibitionConfig.Data.SnowFlake.NodeNum)
st, err = time.Parse("2006-01-02", exhibitionConfig.Data.SnowFlake.StartTime)
if err != nil {
panic(err)
}
snowflake.Epoch = st.UnixNano() / 1000000
node, errS := snowflake.NewNode(int64(nodeNum))
if errS != nil {
panic(errS)
}
return node
}
func GenIDInt64() int64 {
return app.ModuleClients.SfNode.Generate().Int64()
}
func GetIDBase64() string {
return app.ModuleClients.SfNode.Generate().Base64()
}

@ -0,0 +1,51 @@
package tracing
import (
exhibitionConfig "exhibition-register/config"
"io"
"time"
"github.com/google/wire"
"github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go"
jaegerConfig "github.com/uber/jaeger-client-go/config"
"go.uber.org/zap"
)
var Provider = wire.NewSet(NewTracing)
type JaegerProvider struct {
Tracer opentracing.Tracer
Closer io.Closer
}
//var JaegerPoint *JaegerProvider
func NewTracing() (jaegerProvider *JaegerProvider) {
if exhibitionConfig.Data.Jaeger.Open != "true" {
return
}
jaegerProvider = &JaegerProvider{}
cfg := jaegerConfig.Configuration{
ServiceName: "exhibition-register",
Sampler: &jaegerConfig.SamplerConfig{
Type: jaeger.SamplerTypeRemote,
Param: 1,
},
Reporter: &jaegerConfig.ReporterConfig{
LocalAgentHostPort: exhibitionConfig.Data.Jaeger.Addr,
LogSpans: true,
BufferFlushInterval: 5 * time.Second,
},
}
nativeTracerIo, closerIo, err := cfg.NewTracer(jaegerConfig.Logger(jaeger.StdLogger))
if err != nil {
zap.L().Error("nativeTracer err", zap.Error(err))
return
}
opentracing.SetGlobalTracer(nativeTracerIo)
jaegerProvider.Tracer = nativeTracerIo
jaegerProvider.Closer = closerIo
//JaegerPoint = jaegerProvider
return
}

@ -0,0 +1,75 @@
package utils
import (
"bytes"
"fmt"
"go.uber.org/zap"
"io/ioutil"
"net/http"
)
func Post(url string, jsonStr []byte) (statusCode int, result string) {
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
statusCode = resp.StatusCode
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("post url:", url)
fmt.Println("response Headers:", resp.Header)
fmt.Println("response Body:", string(body))
result = string(body)
zap.L().Info("post", zap.Any("url", url), zap.Any("jsonStr", jsonStr), zap.Any("result", result))
return
}
func Get(url string) (statusCode int, result string) {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
statusCode = resp.StatusCode
fmt.Println("response StatusCode:", resp.StatusCode)
fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header)
body, _ := ioutil.ReadAll(resp.Body)
result = string(body)
fmt.Println("response Body:", string(body))
zap.L().Info("Get", zap.Any("url", url), zap.Any("result", result))
return
}
func PutFromFileUrlWithStream(url, fileName, fileUrl string) (statusCode int, result string) {
file, err := http.Get(fileUrl)
if err != nil {
panic(err)
}
defer file.Body.Close()
fileBody, _ := ioutil.ReadAll(file.Body)
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(fileBody))
req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("x-oss-meta-rawfilename", fileName)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
//panic(err)
return 400, "执行文件上传失败"
}
defer resp.Body.Close()
statusCode = resp.StatusCode
body, _ := ioutil.ReadAll(resp.Body)
result = string(body)
fmt.Println("put url:", url)
fmt.Println("fileName :", fileName)
fmt.Println("response Headers:", resp.Header)
//fmt.Println("response Body:", string(body))
fmt.Println("response StatusCode:", statusCode)
//zap.L().Info("post", zap.Any("url", url), zap.Any("jsonStr", bytes.NewBuffer(fileBody).String()), zap.Any("result", result))
return
}

@ -0,0 +1,11 @@
package utils
import "strings"
import "errors"
func SubstrError(err error) (sErr error) {
start := strings.Index(err.Error(), ":")
msg := err.Error()[start+2:]
sErr = errors.New(msg)
return
}

@ -0,0 +1,50 @@
package utils
import (
"errors"
"exhibition-register/pkg/msg"
"go.uber.org/zap"
"time"
)
const (
DateTimeFormat = "2006-01-02 15:04:05"
DateFormat = "2006-01-02"
DateFormatYmdHisDot = "2006.01.02 15:04"
DateFormatMonth = "2006年01月02日 15:04"
)
func DatetimeToTimes(datetime string, dateFormat string) (times int32, err error) {
if datetime == "" {
times = 0
return
}
loc, _ := time.LoadLocation("Asia/Shanghai")
t, err := time.ParseInLocation(dateFormat, datetime, loc)
if err != nil {
zap.L().Error("DatetimeToTimes err:"+datetime+":", zap.Error(err))
err = errors.New(msg.ErrorDatetime)
return
}
times = int32(t.Unix())
return
}
func TimesToDatetime(times int32, format string) string {
if times == 0 {
return ""
}
t := time.Unix(int64(times), 0)
if format == "" {
format = DateTimeFormat
}
return t.Format(format)
}
func MonthInfo() (startTime int64, endTime int64) {
timeNow := time.Now()
timeToday := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 0, 0, 0, 0, timeNow.Location()) // 获取当天0点时间 time类型
startTime = timeToday.AddDate(0, 0, -timeToday.Day()+1).Unix() // 获取本月第一天0点 时间戳类型
endTime = timeToday.AddDate(0, 1, -timeToday.Day()+1).Unix()
return
}

@ -0,0 +1,8 @@
package utils
import "github.com/nacos-group/nacos-sdk-go/inner/uuid"
func GetUUID() string {
id, _ := uuid.NewV4()
return id.String()
}
Loading…
Cancel
Save