github.com/puellanivis/breton@v0.2.16/lib/files/httpfiles/writer.go (about) 1 package httpfiles 2 3 import ( 4 "context" 5 "net/http" 6 "net/url" 7 8 "github.com/puellanivis/breton/lib/files" 9 "github.com/puellanivis/breton/lib/files/wrapper" 10 ) 11 12 type writer struct { 13 *wrapper.Writer 14 *request 15 } 16 17 func (w *writer) Name() string { 18 return w.request.Name() 19 } 20 21 func (w *writer) Header() (http.Header, error) { 22 return w.request.req.Header, nil 23 } 24 25 func (h *handler) Create(ctx context.Context, uri *url.URL) (files.Writer, error) { 26 uri = elideDefaultPort(uri) 27 28 cl, ok := getClient(ctx) 29 if !ok { 30 cl = http.DefaultClient 31 } 32 33 req := newHTTPRequest(http.MethodPost, uri) 34 req = req.WithContext(ctx) 35 36 if ua, ok := getUserAgent(ctx); ok { 37 req.Header.Set("User-Agent", ua) 38 } 39 40 r := &request{ 41 name: uri.String(), 42 req: req, 43 } 44 45 // The http.Writer does not actually perform the http.Request until wrapper.Sync is called, 46 // So there is no need for complex synchronization like the httpfiles.Reader needs. 47 w := wrapper.NewWriter(ctx, uri, func(b []byte) error { 48 if r.req.Header.Get("Content-Type") == "" { 49 r.req.Header.Set("Content-Type", http.DetectContentType(b)) 50 } 51 _ = r.SetBody(b) 52 53 resp, err := cl.Do(r.req) 54 if err != nil { 55 return files.PathError("write", r.name, err) 56 } 57 58 if err := files.Discard(resp.Body); err != nil { 59 return err 60 } 61 62 if err := getErr(resp); err != nil { 63 return files.PathError("write", r.name, err) 64 } 65 66 return nil 67 }) 68 69 return &writer{ 70 request: r, 71 Writer: w, 72 }, nil 73 }