github.com/richardwilkes/toolbox@v1.121.0/xio/retrieve.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package xio 11 12 import ( 13 "context" 14 "io" 15 "net/http" 16 "net/url" 17 "os" 18 "strings" 19 20 "github.com/richardwilkes/toolbox/errs" 21 ) 22 23 // RetrieveData loads the bytes from the given file path or URL of type file, http, or https. 24 func RetrieveData(filePathOrURL string) ([]byte, error) { 25 return RetrieveDataWithContext(context.Background(), filePathOrURL) 26 } 27 28 // RetrieveDataWithContext loads the bytes from the given file path or URL of type file, http, or https. 29 func RetrieveDataWithContext(ctx context.Context, filePathOrURL string) ([]byte, error) { 30 if strings.HasPrefix(filePathOrURL, "http://") || 31 strings.HasPrefix(filePathOrURL, "https://") || 32 strings.HasPrefix(filePathOrURL, "file://") { 33 return RetrieveDataFromURLWithContext(ctx, filePathOrURL) 34 } 35 data, err := os.ReadFile(filePathOrURL) 36 if err != nil { 37 return nil, errs.NewWithCause(filePathOrURL, err) 38 } 39 return data, nil 40 } 41 42 // RetrieveDataFromURL loads the bytes from the given URL of type file, http, or https. 43 func RetrieveDataFromURL(urlStr string) ([]byte, error) { 44 return RetrieveDataFromURLWithContext(context.Background(), urlStr) 45 } 46 47 // RetrieveDataFromURLWithContext loads the bytes from the given URL of type file, http, or https. 48 func RetrieveDataFromURLWithContext(ctx context.Context, urlStr string) ([]byte, error) { 49 u, err := url.Parse(urlStr) 50 if err != nil { 51 return nil, errs.NewWithCause(urlStr, err) 52 } 53 var data []byte 54 switch u.Scheme { 55 case "file": 56 if data, err = os.ReadFile(u.Path); err != nil { 57 return nil, errs.NewWithCause(urlStr, err) 58 } 59 return data, nil 60 case "http", "https": 61 var req *http.Request 62 req, err = http.NewRequestWithContext(ctx, http.MethodGet, urlStr, http.NoBody) 63 if err != nil { 64 return nil, errs.NewWithCause("unable to create request", err) 65 } 66 var rsp *http.Response 67 if rsp, err = http.DefaultClient.Do(req); err != nil { 68 return nil, errs.NewWithCause(urlStr, err) 69 } 70 defer DiscardAndCloseIgnoringErrors(rsp.Body) 71 if rsp.StatusCode < 200 || rsp.StatusCode > 299 { 72 return nil, errs.NewWithCause(urlStr, errs.Newf("received status %d (%s)", rsp.StatusCode, rsp.Status)) 73 } 74 data, err = io.ReadAll(rsp.Body) 75 if err != nil { 76 return nil, errs.NewWithCause(urlStr, err) 77 } 78 return data, nil 79 default: 80 return nil, errs.Newf("invalid url: %s", urlStr) 81 } 82 }