package rest import ( "bytes" "encoding/json" "io" "log" "mime/multipart" "net/http" "net/textproto" mjson "git.ali33.ru/fcg-xvii/go-tools/json" ) func NewResponse() *Response { return &Response{ data: make(mjson.Map), files: make(map[string]io.ReadCloser), } } type Response struct { data mjson.Map files map[string]io.ReadCloser err error errArgs mjson.Map code int } func (s *Response) KeySet(key string, val any) { s.data[key] = val } func (s *Response) FileSet(name string, file io.ReadCloser) { s.files[name] = file } func (s *Response) SetError(code int, err error) { s.code = code s.err = err } func (s *Response) Close() { for _, file := range s.files { file.Close() } } func (s *Response) Send(w http.ResponseWriter) error { log.Println("SEND...") defer s.Close() if s.err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(s.code) body := mjson.Map{ "error": s.err.Error(), "args": s.errArgs, } w.Write(body.JSON()) return nil } // Если есть файлы, то используем multipart if len(s.files) > 0 { var b bytes.Buffer writer := multipart.NewWriter(&b) // Добавляем JSON-данные как часть partHeader := make(textproto.MIMEHeader) partHeader.Set("Content-Type", "application/json") partHeader.Set("Content-Disposition", `form-data; name="data"`) dataPart, err := writer.CreatePart(partHeader) if err != nil { return err } if err := json.NewEncoder(dataPart).Encode(s.data); err != nil { return err } // Добавляем файлы for filename, file := range s.files { part, err := writer.CreateFormFile("file", filename) if err != nil { return err } if _, err := io.Copy(part, file); err != nil { return err } } // Закрываем multipart writer if err := writer.Close(); err != nil { return err } // Отправляем multipart response w.Header().Set("Content-Type", writer.FormDataContentType()) w.Write(b.Bytes()) } else { // Если нет файлов, просто отправляем JSON w.Header().Set("Content-Type", "application/json") return json.NewEncoder(w).Encode(s.data) } return nil } /////////////////////////////////////////// func ResponseError(err error, args mjson.Map, code int) *Response { return &Response{ code: code, err: err, errArgs: args, } } /////////////////////////////////////////// func ResponseErrKeyNotExists(key string) *Response { return ResponseError( ErrKeyNotExists, mjson.Map{ "key": key, }, 500, ) } func ResponseErrKeyInvalidType(key, kType string) *Response { return ResponseError( ErrKeyInvalidType, mjson.Map{ "key": key, "type": kType, }, 500, ) } func ResponseNotFound(data mjson.Map) *Response { return &Response{ code: 404, err: ErrNotFound, errArgs: data, } }