add storage and mux handle with handlers
This commit is contained in:
25
handler/encoders/json.go
Normal file
25
handler/encoders/json.go
Normal 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}))
|
||||
}
|
51
handler/encoders/jsonpb.go
Normal file
51
handler/encoders/jsonpb.go
Normal 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
67
handler/errors.go
Normal 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})
|
||||
}
|
@@ -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
34
handler/mapping.go
Normal 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
76
handler/writer.go
Normal 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)
|
||||
}
|
Reference in New Issue
Block a user