github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/client/icons.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package client 21 22 import ( 23 "context" 24 "fmt" 25 "io/ioutil" 26 "regexp" 27 28 "golang.org/x/xerrors" 29 ) 30 31 // Icon represents the icon of an installed snap 32 type Icon struct { 33 Filename string 34 Content []byte 35 } 36 37 var contentDispositionMatcher = regexp.MustCompile(`attachment; filename=(.+)`).FindStringSubmatch 38 39 // Icon returns the Icon belonging to an installed snap 40 func (c *Client) Icon(pkgID string) (*Icon, error) { 41 const errPrefix = "cannot retrieve icon" 42 43 response, cancel, err := c.rawWithTimeout(context.Background(), "GET", fmt.Sprintf("/v2/icons/%s/icon", pkgID), nil, nil, nil, nil) 44 if err != nil { 45 fmt := "%s: failed to communicate with server: %w" 46 return nil, xerrors.Errorf(fmt, errPrefix, err) 47 } 48 defer cancel() 49 defer response.Body.Close() 50 51 if response.StatusCode != 200 { 52 return nil, fmt.Errorf("%s: Not Found", errPrefix) 53 } 54 55 matches := contentDispositionMatcher(response.Header.Get("Content-Disposition")) 56 57 if matches == nil || matches[1] == "" { 58 return nil, fmt.Errorf("%s: cannot determine filename", errPrefix) 59 } 60 61 content, err := ioutil.ReadAll(response.Body) 62 if err != nil { 63 return nil, fmt.Errorf("%s: %s", errPrefix, err) 64 } 65 66 icon := &Icon{ 67 Filename: matches[1], 68 Content: content, 69 } 70 71 return icon, nil 72 }