github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/ais/s3/err.go (about) 1 // Package s3 provides Amazon S3 compatibility layer 2 /* 3 * Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package s3 6 7 import ( 8 "encoding/xml" 9 "fmt" 10 "net/http" 11 "strings" 12 13 "github.com/NVIDIA/aistore/api/apc" 14 "github.com/NVIDIA/aistore/cmn" 15 "github.com/NVIDIA/aistore/cmn/cos" 16 "github.com/NVIDIA/aistore/cmn/debug" 17 "github.com/NVIDIA/aistore/core" 18 "github.com/NVIDIA/aistore/memsys" 19 ) 20 21 const ErrPrefix = "aws-error" 22 23 type Error struct { 24 Code string 25 Message string 26 Resource string 27 RequestID string `xml:"RequestId"` 28 } 29 30 func (e *Error) mustMarshal(sgl *memsys.SGL) { 31 sgl.Write([]byte(xml.Header)) 32 err := xml.NewEncoder(sgl).Encode(e) 33 debug.AssertNoErr(err) 34 } 35 36 // with user-friendly tip 37 func WriteMptErr(w http.ResponseWriter, r *http.Request, err error, ecode int, lom *core.LOM, uploadID string) { 38 // specifically, for s3cmd example 39 name := strings.Replace(lom.Cname(), apc.AISScheme+apc.BckProviderSeparator, apc.S3Scheme+apc.BckProviderSeparator, 1) 40 s3cmd := "s3cmd abortmp " + name + " " + uploadID 41 if len(s3cmd) > 50 { 42 s3cmd = "\n " + s3cmd 43 } 44 e := fmt.Errorf("%v\nUse upload ID %q to cleanup, e.g.: %s", err, uploadID, s3cmd) 45 if ecode == 0 { 46 ecode = http.StatusInternalServerError 47 } 48 WriteErr(w, r, e, ecode) 49 } 50 51 func WriteErr(w http.ResponseWriter, r *http.Request, err error, ecode int) { 52 var ( 53 out Error 54 in *cmn.ErrHTTP 55 ok bool 56 allocated bool 57 ) 58 if in, ok = err.(*cmn.ErrHTTP); !ok { 59 in = cmn.InitErrHTTP(r, err, ecode) 60 allocated = true 61 } 62 out.Message = in.Message 63 switch { 64 case cmn.IsErrBucketAlreadyExists(err): 65 out.Code = "BucketAlreadyExists" 66 case cmn.IsErrBckNotFound(err): 67 out.Code = "NoSuchBucket" 68 case in.TypeCode != "": 69 out.Code = in.TypeCode 70 default: 71 l := len(ErrPrefix) 72 // e.g. "aws-error[NotFound: blah]" as per backend/aws.go _awsErr() formatting 73 if strings.HasPrefix(out.Message, ErrPrefix) { 74 if i := strings.Index(out.Message[l+1:], ":"); i > 4 { 75 code := out.Message[l+1 : l+i+1] 76 if cos.IsAlphaNice(code) && code[0] >= 'A' && code[0] <= 'Z' { 77 out.Code = code 78 } 79 } 80 } 81 } 82 sgl := memsys.PageMM().NewSGL(0) 83 out.mustMarshal(sgl) 84 85 w.Header().Set(cos.HdrContentType, cos.ContentXML) 86 w.Header().Set(cos.HdrContentTypeOptions, "nosniff") 87 88 w.WriteHeader(in.Status) 89 sgl.WriteTo2(w) 90 sgl.Free() 91 if allocated { 92 cmn.FreeHterr(in) 93 } 94 }