| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 | package svcimport (	"encoding/json"	"fmt"	"net/http"	"golib/features/mo"	"golib/infra/ii"	"golib/network")func NewHTTPHandler(items ii.Items) http.Handler {	return &httpHandler{items: items}}const (	// Method Post	cmdInsertOne  = "insertOne"	cmdInsertMany = "insertMany"	cmdUpdateOne  = "updateOne"	cmdUpdateMany = "updateMany"	cmdUpdateById = "updateById"	cmdFindOne    = "findOne"	cmdFind       = "find"	cmdCount      = "count"	cmdDeleteOne  = "deleteOne"	cmdDeleteMany = "deleteMany")var (	actionMap = map[string]struct{}{		cmdInsertOne:  {},		cmdInsertMany: {},		cmdUpdateOne:  {},		cmdUpdateMany: {},		cmdUpdateById: {},		cmdDeleteOne:  {},		cmdDeleteMany: {},		cmdFind:       {},		cmdFindOne:    {},		cmdCount:      {},	})// action: insertOne/insertMany/updateOne/updateMany/deleteOne/deleteMany/find/findOne// Request: {"action":"insert", "itemName":"test.test", "fields": {"name":"xiaoming","age":3.1415}}// Response: {"action":"insert", "itemName": "test.test", "ret":"success", "result":"","fields":{"name":"required"}}type httpHandleBody struct {	CMD      string `json:"cmd"` // CMD 本次请求需要执行的命令	ItemName string `json:"itemName"`	Data     any    `json:"data"` // Data 数据类型根据 action 变化	ExtData  any    `json:"extData"`}type httpHandler struct {	items ii.Items	user  ii.User}func (f *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {	cmd, itemName, err := ii.SplitPATH(r.URL.Path)	if err != nil {		http.Error(w, err.Error(), http.StatusForbidden)		return	}	if _, ok := actionMap[cmd]; !ok {		http.Error(w, "unknown cmd", http.StatusNotFound)		return	}	if _, ok := f.items.Has(itemName); !ok {		http.Error(w, ErrItemNotfound.Error(), http.StatusNotFound)		return	}	b, err := network.HTTP.ReadRequestBody(w, r, 4096)	if err != nil {		network.HTTP.Error(w, http.StatusBadRequest)		return	}	var hrb httpHandleBody	if err = json.Unmarshal(b, &hrb); err != nil {		network.HTTP.Error(w, http.StatusBadRequest)		return	}	hrb.ItemName = itemName	hrb.CMD = cmd	switch hrb.CMD {	case cmdInsertOne:		f.handleInsertOne(w, &hrb)	case cmdInsertMany:		f.handleInsertMany(w, &hrb)	case cmdUpdateOne:		f.handleUpdateOne(w, &hrb)	case cmdUpdateMany:		f.handleUpdateMany(w, &hrb)	case cmdUpdateById:		f.handleUpdateByID(w, &hrb)	case cmdDeleteOne:		f.handleDeleteOne(w, &hrb)	case cmdDeleteMany:		f.handleDeleteMany(w, &hrb)	case cmdFindOne:		f.handleFindOne(w, &hrb)	case cmdFind:		f.handleFind(w, &hrb)	case cmdCount:		f.handleCount(w, &hrb)	}}func (f *httpHandler) handleFind(w http.ResponseWriter, hrb *httpHandleBody) {	filter, err := f.handleFilterData(hrb.Data)	if err != nil {		f.respJsonErr(w, err, http.StatusBadRequest)		return	}	rows, err := svc.Find(hrb.ItemName, filter)	if err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     rows,	}	f.respJson(w, resp)}func (f *httpHandler) handleFindOne(w http.ResponseWriter, hrb *httpHandleBody) {	filter, err := f.handleFilterData(hrb.Data)	if err != nil {		f.respJsonErr(w, err, http.StatusBadRequest)		return	}	row, err := svc.FindOne(hrb.ItemName, filter)	if err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     row,	}	f.respJson(w, resp)}func (f *httpHandler) handleInsertOne(w http.ResponseWriter, hrb *httpHandleBody) {	data, ok := hrb.Data.(map[string]interface{})	if !ok {		f.respJsonErr(w, ErrDataError, http.StatusBadRequest)		return	}	oid, err := svc.InsertOne(hrb.ItemName, data)	if err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     oid,	}	f.respJson(w, resp)}func (f *httpHandler) handleInsertMany(w http.ResponseWriter, hrb *httpHandleBody) {	data, ok := hrb.Data.([]interface{})	if !ok {		f.respJsonErr(w, ErrDataError, http.StatusBadRequest)		return	}	oidList, err := svc.InsertMany(hrb.ItemName, data)	if err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     oidList,	}	f.respJson(w, resp)}func (f *httpHandler) handleUpdateOne(w http.ResponseWriter, hrb *httpHandleBody) {	filter, update, err := f.handleUpdateData(hrb)	if err != nil {		f.respJsonErr(w, err, http.StatusBadRequest)		return	}	if err = svc.UpdateOne(hrb.ItemName, filter, update); err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     nil,	}	f.respJson(w, resp)}func (f *httpHandler) handleUpdateByID(w http.ResponseWriter, hrb *httpHandleBody) {	idStr, ok := hrb.Data.(string)	if !ok {		f.respJsonErr(w, ErrDataError, http.StatusBadRequest)		return	}	oid, err := mo.ID.From(idStr)	if err != nil {		f.respJsonErr(w, ErrDataError, http.StatusBadRequest)		return	}	update, ok := hrb.ExtData.(map[string]interface{})	if !ok {		f.respJsonErr(w, ErrDataError, http.StatusBadRequest)		return	}	if err = svc.UpdateByID(hrb.ItemName, oid, update); err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     nil,	}	f.respJson(w, resp)}func (f *httpHandler) handleUpdateMany(w http.ResponseWriter, hrb *httpHandleBody) {	filter, update, err := f.handleUpdateData(hrb)	if err != nil {		f.respJsonErr(w, err, http.StatusBadRequest)		return	}	if err = svc.UpdateMany(hrb.ItemName, filter, update); err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     nil,	}	f.respJson(w, resp)}func (f *httpHandler) handleCount(w http.ResponseWriter, hrb *httpHandleBody) {	var (		total int64		err   error	)	if hrb.Data == nil || hrb.Data == "" {		total, err = svc.EstimatedDocumentCount(hrb.ItemName)	} else {		filter, err := f.handleFilterData(hrb.Data)		if err != nil {			f.respJsonErr(w, err, http.StatusBadRequest)			return		}		total, err = svc.CountDocuments(hrb.ItemName, filter)	}	if err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     total,	}	f.respJson(w, resp)}func (f *httpHandler) handleDeleteOne(w http.ResponseWriter, hrb *httpHandleBody) {	filter, err := f.handleFilterData(hrb.Data)	if err != nil {		f.respJsonErr(w, err, http.StatusBadRequest)		return	}	if err = svc.DeleteOne(hrb.ItemName, filter); err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     nil,	}	f.respJson(w, resp)}func (f *httpHandler) handleDeleteMany(w http.ResponseWriter, hrb *httpHandleBody) {	filter, err := f.handleFilterData(hrb.Data)	if err != nil {		f.respJsonErr(w, err, http.StatusBadRequest)		return	}	if err = svc.DeleteMany(hrb.ItemName, filter); err != nil {		f.respJsonErr(w, err, http.StatusInternalServerError)		return	}	resp := &httpHandleBody{		CMD:      hrb.CMD,		ItemName: hrb.ItemName,		Data:     nil,	}	f.respJson(w, resp)}func (f *httpHandler) handleUpdateData(hrb *httpHandleBody) (mo.D, mo.M, error) {	filter, err := f.handleFilterData(hrb.Data)	if err != nil {		return nil, nil, err	}	update, ok := hrb.ExtData.(map[string]interface{})	if !ok {		return nil, nil, err	}	return filter, update, nil}func (f *httpHandler) handleFilterData(data any) (mo.D, error) {	b, err := mo.MarshalExtJSON(data, false, true)	if err != nil {		return nil, err	}	var filter mo.D	if err = mo.UnmarshalExtJSON(b, false, &filter); err != nil {		return nil, err	}	return filter, nil}func (f *httpHandler) respJson(w http.ResponseWriter, v interface{}) {	p, err := json.Marshal(v)	if err != nil {		http.Error(w, err.Error(), http.StatusInternalServerError)		return	}	w.Header().Set("Content-Type", network.HTTPContentTypeJson)	w.WriteHeader(http.StatusOK)	_, _ = w.Write(p)}func (f *httpHandler) respJsonErr(w http.ResponseWriter, err error, code int) {	w.Header().Set("Content-Type", network.HTTPContentTypeJson)	w.WriteHeader(code)	_, _ = w.Write([]byte(fmt.Sprintf(`{"result":"%s"}`, err)))}
 |