add storage and mux handle with handlers

This commit is contained in:
2023-08-09 14:31:23 +03:00
parent fb0ad62f0e
commit bbb9174d8a
22 changed files with 1996 additions and 194 deletions

25
handler/encoders/json.go Normal file
View File

@@ -0,0 +1,25 @@
package encoders
import (
"encoding/json"
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
"net/http"
"github.com/pkg/errors"
)
type JSON struct{}
func (*JSON) Success(rw http.ResponseWriter, response interface{}) error {
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
rw.WriteHeader(http.StatusOK)
return errors.WithStack(json.NewEncoder(rw).Encode(response))
}
func (*JSON) Error(rw http.ResponseWriter, err *pb.Error, status int) error {
rw.Header().Set("Content-Type", "application/problem+json; charset=utf-8")
rw.WriteHeader(status)
return errors.WithStack(json.NewEncoder(rw).Encode(&pb.ErrorRsp{Error: err}))
}

View File

@@ -0,0 +1,51 @@
package encoders
import (
"github.com/pkg/errors"
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"io"
"net/http"
)
var ErrWrongResponseType = errors.New("JSONProto: wrong response message type")
type JSONProto struct {
m protojson.MarshalOptions
}
func NewJSONProto() *JSONProto {
return &JSONProto{m: protojson.MarshalOptions{
EmitUnpopulated: true,
UseProtoNames: false,
}}
}
func (e *JSONProto) Success(rw http.ResponseWriter, response interface{}) error {
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
rw.WriteHeader(http.StatusOK)
if v, ok := response.(proto.Message); ok {
return errors.WithStack(e.Fmarshal(rw, v))
}
return ErrWrongResponseType
}
func (e *JSONProto) Error(rw http.ResponseWriter, err *pb.Error, status int) error {
rw.Header().Set("Content-Type", "application/problem+json; charset=utf-8")
rw.WriteHeader(status)
return errors.WithStack(e.Fmarshal(rw, &pb.ErrorRsp{Error: err}))
}
func (e *JSONProto) Fmarshal(w io.Writer, m proto.Message) error {
b, err := e.m.Marshal(m)
if len(b) > 0 {
if _, err = w.Write(b); err != nil {
return err
}
}
return err
}

67
handler/errors.go Normal file
View File

@@ -0,0 +1,67 @@
package handler
import "github.com/pkg/errors"
type UnmarshalError struct {
err error
}
func (e *UnmarshalError) Error() string {
return e.err.Error()
}
func (e *UnmarshalError) Unwrap() error {
return e.err
}
func NewUnmarshalError(err error) error {
return errors.WithStack(&UnmarshalError{err: err})
}
type InternalError struct {
Err error
}
func (e *InternalError) Error() string {
return e.Err.Error()
}
func NewInternalError(err error) error {
return errors.WithStack(&InternalError{Err: err})
}
type ParametersMissingError struct {
Err error
}
func (e *ParametersMissingError) Error() string {
return e.Err.Error()
}
func NewParametersMissingError(err error) error {
return errors.WithStack(&ParametersMissingError{Err: err})
}
type NotFoundError struct {
Err error
}
func (e *NotFoundError) Error() string {
return e.Err.Error()
}
func NewNotFoundError(err error) error {
return errors.WithStack(&NotFoundError{Err: err})
}
type ValidationError struct {
Err error
}
func (e *ValidationError) Error() string {
return e.Err.Error()
}
func NewValidationError(err error) error {
return errors.WithStack(&ValidationError{Err: err})
}

View File

@@ -2,39 +2,60 @@ package handler
import (
"context"
"go.unistack.org/unistack-org/pkgdash/proto/go_generate"
cmsstorage "go.unistack.org/cms-service/storage"
"go.unistack.org/micro/v3"
"go.unistack.org/micro/v3/errors"
"go.unistack.org/unistack-org/pkgdash/config"
"golang.org/x/mod/sumdb/storage"
"go.unistack.org/unistack-org/pkgdash/models"
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
"go.unistack.org/unistack-org/pkgdash/storage"
"net/http"
)
type Handler struct {
//db *xorm.Engine
svc micro.Service
store storage.Storage
writer writer
}
func (h *Handler) ListPackage(ctx context.Context, req *go_generate.ListPackageReq, rsp *go_generate.ListPackageRsp) error {
//TODO implement me
panic("implement me")
func (h *Handler) ListPackage(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := h.svc.Logger()
logger.Debug(ctx, "Start getListPackage")
dbRsp, err := h.store.List(ctx)
if err != nil {
logger.Errorf(ctx, "error db response: %v", err)
h.writer.Response(ctx, w, err)
return
}
rsp := new(pb.ListPackageRsp)
rsp.Packages = models.ListPackage(dbRsp).Mapping()
logger.Debug(ctx, "Success finish getListPackage")
h.writer.Response(ctx, w, rsp)
}
func (h *Handler) UpdateInfo(ctx context.Context, req *go_generate.UpdateInfoPackageRsp, rsp *go_generate.UpdateInfoPackageReq) error {
//TODO implement me
panic("implement me")
func (h *Handler) UpdateInfo(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := h.svc.Logger()
logger.Debug(ctx, "Start UpdateInfo")
// TODO
}
func (h *Handler) AddComment(ctx context.Context, req *go_generate.CommentRsp, rsp *go_generate.CommentReq) error {
//TODO implement me
panic("implement me")
func (h *Handler) AddComment(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := h.svc.Logger()
logger.Debug(ctx, "Start AddComment")
// TODO
}
func NewHandler(svc micro.Service) *Handler {
return &Handler{svc: svc}
func NewHandler(svc micro.Service, w writer) *Handler {
return &Handler{svc: svc, writer: w}
}
func (h *Handler) Init(ctx context.Context) error {

34
handler/mapping.go Normal file
View File

@@ -0,0 +1,34 @@
package handler
import (
"errors"
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
"net/http"
"golang.org/x/net/context"
)
const (
internalErrorCode = "1"
badRequestCode = "2"
notFoundErrorCode = "3"
)
func mapError(ctx context.Context, err error) (result *pb.Error, status int) {
status = http.StatusBadRequest
switch errors.Unwrap(err).(type) {
case *UnmarshalError:
result = &pb.Error{Code: badRequestCode, Title: "Bad request"}
case *ParametersMissingError:
result = &pb.Error{Code: badRequestCode, Title: "Required parameters are missing"}
case *NotFoundError:
result = &pb.Error{Code: notFoundErrorCode, Title: "Not found"}
status = http.StatusNotFound
default:
status = http.StatusInternalServerError
result = &pb.Error{Code: internalErrorCode, Title: "Internal error", Details: err.Error()}
}
return
}

76
handler/writer.go Normal file
View File

@@ -0,0 +1,76 @@
package handler
import (
"context"
"go.unistack.org/micro/v4/logger"
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
"net/http"
"github.com/pkg/errors"
)
type encoder interface {
Success(rw http.ResponseWriter, response interface{}) error
Error(rw http.ResponseWriter, err *pb.Error, status int) error
}
type writer interface {
Response(ctx context.Context, rw http.ResponseWriter, value interface{})
}
type stackTracer interface {
StackTrace() errors.StackTrace
}
type Writer struct {
encoder encoder
}
func NewWriter(encoder encoder) (*Writer, error) {
if encoder == nil {
return nil, errors.New("empty encoder")
}
return &Writer{encoder: encoder}, nil
}
func (w *Writer) Response(ctx context.Context, rw http.ResponseWriter, value interface{}) {
var err error
if v, ok := value.(error); ok {
err = w.error(ctx, rw, v)
} else {
err = w.success(rw, value)
}
if err != nil {
logger.Error(ctx, "Response writing error: ", err)
}
}
func (w *Writer) error(ctx context.Context, rw http.ResponseWriter, err error) error {
e, status := mapError(ctx, err)
/*
switch {
case status >= http.StatusInternalServerError:
logger.Errorf(ctx, "error: %s, code: %s, http status: %d, uuid: %s", err, e.Code, status, e.Uuid)
if err, ok := err.(stackTracer); ok {
logger.Errorf(ctx, "error stacktrace: %+v, uuid: %s", err.StackTrace(), e.Uuid)
}
default:
logger.Infof(ctx, "error: %s, code: %s, http status: %d, uuid: %s", err, e.Code, status, e.Uuid)
if err, ok := err.(stackTracer); ok {
logger.Infof(ctx, "error stacktrace: %+v, uuid: %s", err.StackTrace(), e.Uuid)
}
}
*/
return w.encoder.Error(rw, e, status)
}
func (w *Writer) success(rw http.ResponseWriter, value interface{}) error {
return w.encoder.Success(rw, value)
}