merge master

master
李伟乐 2 years ago
commit ec4b0fb91e
  1. 1
      app.go
  2. 5
      cmd/kit/main.go
  3. 93
      errors/errors.go
  4. 226
      errors/errors.pb.go
  5. 16
      errors/errors.proto
  6. 16
      errors/warp.go
  7. 1
      middleware/logger.go
  8. 22
      test/main.go
  9. 16
      third_party/errors/errors.proto
  10. 0
      third_party/google/api/annotations.proto
  11. 0
      third_party/google/api/client.proto
  12. 0
      third_party/google/api/field_behavior.proto
  13. 0
      third_party/google/api/http.proto
  14. 0
      third_party/google/api/httpbody.proto
  15. 0
      third_party/google/protobuf/any.proto
  16. 0
      third_party/google/protobuf/api.proto
  17. 0
      third_party/google/protobuf/compiler/plugin.proto
  18. 0
      third_party/google/protobuf/descriptor.proto
  19. 0
      third_party/google/protobuf/duration.proto
  20. 0
      third_party/google/protobuf/empty.proto
  21. 0
      third_party/google/protobuf/field_mask.proto
  22. 0
      third_party/google/protobuf/source_context.proto
  23. 0
      third_party/google/protobuf/struct.proto
  24. 0
      third_party/google/protobuf/timestamp.proto
  25. 0
      third_party/google/protobuf/type.proto
  26. 0
      third_party/google/protobuf/wrappers.proto
  27. 0
      third_party/validate/validate.proto
  28. 109
      transport/http/calloption.go
  29. 2
      transport/http/codec.go
  30. 76
      transport/http/server.go
  31. 96
      transport/http/status/status.go

@ -10,6 +10,7 @@ import (
"git.diulo.com/mogfee/kit/transport"
"github.com/google/uuid"
"golang.org/x/sync/errgroup"
"os"
"os/signal"
"sync"

@ -25,8 +25,13 @@ func (u *Kit) Generate(plugin *protogen.Plugin) error {
}
u.addImports("context")
u.addImports("git.diulo.com/mogfee/kit/middleware")
<<<<<<< HEAD
u.addImports("git.diulo.com/mogfee/kit/response")
u.addImports("git.diulo.com/mogfee/kit/errors")
=======
u.addImports("git.diulo.com/mogfee/kit/pkg/response")
u.addImports("git.diulo.com/mogfee/kit/pkg/errors")
>>>>>>> 434d858718d87c9c434ae68dc9095f66fb161008
u.addImports("github.com/gin-gonic/gin")
for _, f := range plugin.Files {
if len(f.Services) == 0 {

@ -2,8 +2,9 @@ package errors
import (
"errors"
"fmt"
httpstatus "git.diulo.com/mogfee/kit/transport/http/status"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@ -15,36 +16,69 @@ const (
)
type Error struct {
Status int
Message string
Reason string
Metadata map[string]string
Status
cause error
}
func (e *Error) WithMetadata(data map[string]string) *Error {
err := Clone(e)
err.Metadata = data
return err
func (e *Error) Error() string {
return fmt.Sprintf("error: code = %d reason = %s message = %s metadata = %v cause = %v", e.Code, e.Reason, e.Message, e.Metadata, e.cause)
}
func (s *Error) Error() string {
return s.Message
func (e *Error) Unwarp() error {
return e.cause
}
func New(code int, reason, message string) *Error {
return &Error{
Status: code,
Message: message,
Reason: reason,
Metadata: map[string]string{},
func (e *Error) Is(err error) bool {
if se := new(Error); errors.As(err, &se) {
return se.Code == e.Code && se.Reason == e.Reason
}
return false
}
func (e *Error) WithCause(cause error) *Error {
err := Clone(e)
err.cause = cause
return err
}
func (e *Error) WithMetadata(md map[string]string) *Error {
err := Clone(e)
err.Metadata = md
return err
}
func (e *Error) GRPCStatus() *status.Status {
s, _ := status.New(codes.Code(e.Status), e.Message).
s, _ := status.New(httpstatus.ToGRPCCode(int(e.Code)), e.Message).
WithDetails(&errdetails.ErrorInfo{
Reason: e.Reason,
Metadata: e.Metadata,
})
return s
}
func New(code int, reason, message string) *Error {
return &Error{
Status: Status{
Code: int32(code),
Reason: reason,
Message: message,
},
}
}
func Newf(code int, reason string, format string, a ...any) *Error {
return New(code, reason, fmt.Sprintf(format, a...))
}
func Errorf(code int, reason string, format string, a ...any) *Error {
return New(code, reason, fmt.Sprintf(format, a...))
}
func Code(err error) int {
if err == nil {
return 200
}
return int(FromError(err).Code)
}
func Reason(err error) string {
if err == nil {
return UnknownReason
}
return FromError(err).Reason
}
func Clone(err *Error) *Error {
if err == nil {
return nil
@ -54,18 +88,15 @@ func Clone(err *Error) *Error {
metadata[k] = v
}
return &Error{
Status: err.Status,
cause: err.cause,
Status: Status{
Code: err.Code,
Reason: err.Reason,
Message: err.Message,
Metadata: metadata,
},
}
}
func Code(err error) int {
if err == nil {
return 200
}
return FromError(err).Status
}
func FromError(err error) *Error {
if err == nil {
@ -74,5 +105,17 @@ func FromError(err error) *Error {
if se := new(Error); errors.As(err, &se) {
return se
}
gs, ok := status.FromError(err)
if !ok {
return New(UnknownCode, UnknownReason, err.Error())
}
ret := New(httpstatus.FromGRPCCode(gs.Code()), UnknownReason, gs.Message())
for _, detail := range gs.Details() {
switch d := detail.(type) {
case *errdetails.ErrorInfo:
ret.Reason = d.Reason
return ret.WithMetadata(d.Metadata)
}
}
return ret
}

@ -0,0 +1,226 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v4.22.0
// source: errors.proto
package errors
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Status struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"`
Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
Metadata map[string]string `protobuf:"bytes,4,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *Status) Reset() {
*x = Status{}
if protoimpl.UnsafeEnabled {
mi := &file_errors_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Status) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Status) ProtoMessage() {}
func (x *Status) ProtoReflect() protoreflect.Message {
mi := &file_errors_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Status.ProtoReflect.Descriptor instead.
func (*Status) Descriptor() ([]byte, []int) {
return file_errors_proto_rawDescGZIP(), []int{0}
}
func (x *Status) GetCode() int32 {
if x != nil {
return x.Code
}
return 0
}
func (x *Status) GetReason() string {
if x != nil {
return x.Reason
}
return ""
}
func (x *Status) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
func (x *Status) GetMetadata() map[string]string {
if x != nil {
return x.Metadata
}
return nil
}
var file_errors_proto_extTypes = []protoimpl.ExtensionInfo{
{
ExtendedType: (*descriptorpb.EnumOptions)(nil),
ExtensionType: (*int32)(nil),
Field: 1108,
Name: "errors.default_code",
Tag: "varint,1108,opt,name=default_code",
Filename: "errors.proto",
},
{
ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
ExtensionType: (*int32)(nil),
Field: 1109,
Name: "errors.code",
Tag: "varint,1109,opt,name=code",
Filename: "errors.proto",
},
}
// Extension fields to descriptorpb.EnumOptions.
var (
// optional int32 default_code = 1108;
E_DefaultCode = &file_errors_proto_extTypes[0]
)
// Extension fields to descriptorpb.EnumValueOptions.
var (
// optional int32 code = 1109;
E_Code = &file_errors_proto_extTypes[1]
)
var File_errors_proto protoreflect.FileDescriptor
var file_errors_proto_rawDesc = []byte{
0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc5, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12,
0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74,
0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x72,
0x72, 0x6f, 0x72, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x3a, 0x40, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65,
0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd4,
0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f,
0x64, 0x65, 0x3a, 0x36, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75,
0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd5, 0x08,
0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69,
0x74, 0x2e, 0x64, 0x69, 0x75, 0x6c, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x67, 0x66,
0x65, 0x65, 0x2f, 0x6b, 0x69, 0x74, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x3b, 0x65, 0x72,
0x72, 0x6f, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_errors_proto_rawDescOnce sync.Once
file_errors_proto_rawDescData = file_errors_proto_rawDesc
)
func file_errors_proto_rawDescGZIP() []byte {
file_errors_proto_rawDescOnce.Do(func() {
file_errors_proto_rawDescData = protoimpl.X.CompressGZIP(file_errors_proto_rawDescData)
})
return file_errors_proto_rawDescData
}
var file_errors_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_errors_proto_goTypes = []interface{}{
(*Status)(nil), // 0: errors.Status
nil, // 1: errors.Status.MetadataEntry
(*descriptorpb.EnumOptions)(nil), // 2: google.protobuf.EnumOptions
(*descriptorpb.EnumValueOptions)(nil), // 3: google.protobuf.EnumValueOptions
}
var file_errors_proto_depIdxs = []int32{
1, // 0: errors.Status.metadata:type_name -> errors.Status.MetadataEntry
2, // 1: errors.default_code:extendee -> google.protobuf.EnumOptions
3, // 2: errors.code:extendee -> google.protobuf.EnumValueOptions
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
1, // [1:3] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_errors_proto_init() }
func file_errors_proto_init() {
if File_errors_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_errors_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Status); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_errors_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 2,
NumServices: 0,
},
GoTypes: file_errors_proto_goTypes,
DependencyIndexes: file_errors_proto_depIdxs,
MessageInfos: file_errors_proto_msgTypes,
ExtensionInfos: file_errors_proto_extTypes,
}.Build()
File_errors_proto = out.File
file_errors_proto_rawDesc = nil
file_errors_proto_goTypes = nil
file_errors_proto_depIdxs = nil
}

@ -0,0 +1,16 @@
syntax="proto3";
package errors;
option go_package="git.diulo.com/mogfee/kit/errors;errors";
import "google/protobuf/descriptor.proto";
message Status{
int32 code=1;
string reason=2;
string message=3;
map<string,string>metadata=4;
}
extend google.protobuf.EnumOptions{
int32 default_code=1108;
}
extend google.protobuf.EnumValueOptions{
int32 code=1109;
}

@ -0,0 +1,16 @@
package errors
import (
stderrors "errors"
)
func Is(err, target error) bool {
return stderrors.Is(err, target)
}
func As(err error, target any) bool {
return stderrors.As(err, target)
}
func Unwarp(err error) error {
return stderrors.Unwrap(err)
}

@ -9,7 +9,6 @@ func Logger(logger log.Logger) Middleware {
//helper:=log.NewHelper(logger)
return func(handler Handler) Handler {
return func(ctx context.Context, a any) (any, error) {
//helper.Infof("")
return handler(ctx, a)
}
}

@ -1,16 +1,36 @@
package main
import (
"errors"
"fmt"
"git.diulo.com/mogfee/kit"
"git.diulo.com/mogfee/kit/transport/http"
)
func main() {
app := kit.New(
kit.Name("user-server"),
kit.Server())
kit.Server(appServer()))
fmt.Println("run start")
app.Run()
fmt.Println("run end")
app.Stop()
}
func appServer() *http.Server {
srv := http.NewServer(http.Address("localhost:9019"))
group := srv.Route("/")
group.Handle("GET", "/", func(ctx http.Context) error {
return errors.New("abc ")
})
//group.GET("/", func(ctx http.Context) error {
// return ctx.String(200, "index page")
//})
//group.GET("/hello", func(ctx http.Context) error {
// return ctx.String(200, "hello page")
//})
//group.GET("/error", func(ctx http.Context) error {
// fmt.Println("err 1")
// return errors.New(400, "BAD_REQUEST", "")
//})
return srv
}

@ -0,0 +1,16 @@
syntax="proto3";
package errors;
option go_package="git.diulo.com/mogfee/kit/errors;errors";
import "google/protobuf/descriptor.proto";
message Status{
int32 code=1;
string reason=2;
string message=3;
map<string,string>metadata=4;
}
extend google.protobuf.EnumOptions{
int32 default_code=1108;
}
extend google.protobuf.EnumValueOptions{
int32 code=1109;
}

@ -0,0 +1,109 @@
package http
import (
"net/http"
)
// CallOption configures a Call before it starts or extracts information from
// a Call after it completes.
type CallOption interface {
// before is called before the call is sent to any server. If before
// returns a non-nil error, the RPC fails with that error.
before(*callInfo) error
// after is called after the call has completed. after cannot return an
// error, so any failures should be reported via output parameters.
after(*callInfo, *csAttempt)
}
type callInfo struct {
contentType string
operation string
pathTemplate string
}
// EmptyCallOption does not alter the Call configuration.
// It can be embedded in another structure to carry satellite data for use
// by interceptors.
type EmptyCallOption struct{}
func (EmptyCallOption) before(*callInfo) error { return nil }
func (EmptyCallOption) after(*callInfo, *csAttempt) {}
type csAttempt struct {
res *http.Response
}
// ContentType with request content type.
func ContentType(contentType string) CallOption {
return ContentTypeCallOption{ContentType: contentType}
}
// ContentTypeCallOption is BodyCallOption
type ContentTypeCallOption struct {
EmptyCallOption
ContentType string
}
func (o ContentTypeCallOption) before(c *callInfo) error {
c.contentType = o.ContentType
return nil
}
func defaultCallInfo(path string) callInfo {
return callInfo{
contentType: "application/json",
operation: path,
pathTemplate: path,
}
}
// Operation is serviceMethod call option
func Operation(operation string) CallOption {
return OperationCallOption{Operation: operation}
}
// OperationCallOption is set ServiceMethod for client call
type OperationCallOption struct {
EmptyCallOption
Operation string
}
func (o OperationCallOption) before(c *callInfo) error {
c.operation = o.Operation
return nil
}
// PathTemplate is http path template
func PathTemplate(pattern string) CallOption {
return PathTemplateCallOption{Pattern: pattern}
}
// PathTemplateCallOption is set path template for client call
type PathTemplateCallOption struct {
EmptyCallOption
Pattern string
}
func (o PathTemplateCallOption) before(c *callInfo) error {
c.pathTemplate = o.Pattern
return nil
}
// Header returns a CallOptions that retrieves the http response header
// from server reply.
func Header(header *http.Header) CallOption {
return HeaderCallOption{header: header}
}
// HeaderCallOption is retrieve response header for client call
type HeaderCallOption struct {
EmptyCallOption
header *http.Header
}
func (o HeaderCallOption) after(c *callInfo, cs *csAttempt) {
if cs.res != nil && cs.res.Header != nil {
*o.header = cs.res.Header
}
}

@ -81,7 +81,7 @@ func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, err error) {
return
}
w.Header().Set("Content-Type", httputil.ContentType(codec.Name()))
w.WriteHeader(int(se.Status))
w.WriteHeader(int(se.Status.Code))
_, _ = w.Write(body)
}
func CodeForRequest(r *http.Request, name string) (encoding.Codec, bool) {

@ -213,6 +213,9 @@ func (s *Server) WalkRoute(fn WalkRouteFunc) error {
}
// Route registers an HTTP router.
func (s *Server) Kind() transport.Kind {
return transport.KindHTTP
}
func (s *Server) Route(prefix string, filters ...FilterFunc) *Router {
return newRouter(prefix, s, filters...)
}
@ -242,6 +245,37 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
s.Handler.ServeHTTP(res, req)
}
func (s *Server) Endpoint() (*url.URL, error) {
if err := s.listenAndEndpoint(); err != nil {
return nil, err
}
return s.endpoint, nil
}
func (s *Server) Start(ctx context.Context) error {
if err := s.listenAndEndpoint(); err != nil {
return err
}
s.BaseContext = func(listener net.Listener) context.Context {
return ctx
}
log.Infof("[HTTP] server listening on: %s", s.endpoint)
var err error
if s.tlsConf != nil {
err = s.ServeTLS(s.lis, "", "")
} else {
err = s.Serve(s.lis)
}
if !errors.Is(err, http.ErrServerClosed) {
return err
}
return nil
}
func (s *Server) Stop(ctx context.Context) error {
log.Info("[HTTP] server stopping")
return s.Shutdown(ctx)
}
func (s *Server) filter() mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
@ -266,7 +300,7 @@ func (s *Server) filter() mux.MiddlewareFunc {
operation: pathTemplate,
pathTemplate: pathTemplate,
reqHeader: headerCarrier(req.Header),
replyHeader: headerCarrier(w.Header()),
replyHeader: headerCarrier(req.Header),
request: req,
}
if s.endpoint != nil {
@ -277,46 +311,6 @@ func (s *Server) filter() mux.MiddlewareFunc {
})
}
}
// Endpoint return a real address to registry endpoint.
// examples:
//
// https://127.0.0.1:8000
// Legacy: http://127.0.0.1:8000?isSecure=false
func (s *Server) Endpoint() (*url.URL, error) {
if err := s.listenAndEndpoint(); err != nil {
return nil, err
}
return s.endpoint, nil
}
// Start start the HTTP server.
func (s *Server) Start(ctx context.Context) error {
if err := s.listenAndEndpoint(); err != nil {
return err
}
s.BaseContext = func(net.Listener) context.Context {
return ctx
}
log.Infof("[HTTP] server listening on: %s", s.lis.Addr().String())
var err error
if s.tlsConf != nil {
err = s.ServeTLS(s.lis, "", "")
} else {
err = s.Serve(s.lis)
}
if !errors.Is(err, http.ErrServerClosed) {
return err
}
return nil
}
// Stop stop the HTTP server.
func (s *Server) Stop(ctx context.Context) error {
log.Info("[HTTP] server stopping")
return s.Shutdown(ctx)
}
func (s *Server) listenAndEndpoint() error {
if s.lis == nil {
lis, err := net.Listen(s.network, s.address)

@ -0,0 +1,96 @@
package status
import (
"google.golang.org/grpc/codes"
"net/http"
)
const (
ClientClosed = 499
)
type Converter interface {
ToGRPCCode(code int) codes.Code
FromGRPCCode(code codes.Code) int
}
var DefaultConverter Converter = statusConverter{}
type statusConverter struct {
}
func (s statusConverter) ToGRPCCode(code int) codes.Code {
switch code {
case http.StatusOK:
return codes.OK
case http.StatusBadRequest:
return codes.InvalidArgument
case http.StatusUnauthorized:
return codes.Unauthenticated
case http.StatusForbidden:
return codes.PermissionDenied
case http.StatusNotFound:
return codes.NotFound
case http.StatusConflict:
return codes.Aborted
case http.StatusTooManyRequests:
return codes.ResourceExhausted
case http.StatusInternalServerError:
return codes.Internal
case http.StatusNotImplemented:
return codes.Unimplemented
case http.StatusServiceUnavailable:
return codes.Unavailable
case http.StatusGatewayTimeout:
return codes.DeadlineExceeded
case ClientClosed:
return codes.Canceled
}
return codes.Unknown
}
func (s statusConverter) FromGRPCCode(code codes.Code) int {
switch code {
case codes.OK:
return http.StatusOK
case codes.Canceled:
return ClientClosed
case codes.Unknown:
return http.StatusInternalServerError
case codes.InvalidArgument:
return http.StatusBadRequest
case codes.DeadlineExceeded:
return http.StatusGatewayTimeout
case codes.NotFound:
return http.StatusNotFound
case codes.AlreadyExists:
return http.StatusConflict
case codes.PermissionDenied:
return http.StatusForbidden
case codes.Unauthenticated:
return http.StatusUnauthorized
case codes.ResourceExhausted:
return http.StatusTooManyRequests
case codes.FailedPrecondition:
return http.StatusBadRequest
case codes.Aborted:
return http.StatusConflict
case codes.OutOfRange:
return http.StatusBadRequest
case codes.Unimplemented:
return http.StatusNotImplemented
case codes.Internal:
return http.StatusInternalServerError
case codes.Unavailable:
return http.StatusServiceUnavailable
case codes.DataLoss:
return http.StatusInternalServerError
}
return http.StatusInternalServerError
}
func ToGRPCCode(code int) codes.Code {
return DefaultConverter.ToGRPCCode(code)
}
func FromGRPCCode(code codes.Code) int {
return DefaultConverter.FromGRPCCode(code)
}
Loading…
Cancel
Save