github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/services/marketplace/client.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package marketplace
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"net/url"
    12  	"strings"
    13  
    14  	"github.com/mattermost/mattermost-server/v5/model"
    15  	"github.com/mattermost/mattermost-server/v5/services/httpservice"
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  // Client is the programmatic interface to the marketplace server API.
    20  type Client struct {
    21  	address    string
    22  	httpClient *http.Client
    23  }
    24  
    25  // NewClient creates a client to the marketplace server at the given address.
    26  func NewClient(address string, httpService httpservice.HTTPService) (*Client, error) {
    27  	var httpClient *http.Client
    28  	addressUrl, err := url.Parse(address)
    29  	if err != nil {
    30  		return nil, errors.Wrap(err, "failed to parse marketplace address")
    31  	}
    32  	if addressUrl.Hostname() == "localhost" || addressUrl.Hostname() == "127.0.0.1" {
    33  		httpClient = httpService.MakeClient(true)
    34  	} else {
    35  		httpClient = httpService.MakeClient(false)
    36  	}
    37  
    38  	return &Client{
    39  		address:    address,
    40  		httpClient: httpClient,
    41  	}, nil
    42  }
    43  
    44  // GetPlugins fetches the list of plugins from the configured server.
    45  func (c *Client) GetPlugins(request *model.MarketplacePluginFilter) ([]*model.BaseMarketplacePlugin, error) {
    46  	u, err := url.Parse(c.buildURL("/api/v1/plugins"))
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	request.ApplyToURL(u)
    52  
    53  	resp, err := c.doGet(u.String())
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	defer closeBody(resp)
    58  
    59  	switch resp.StatusCode {
    60  	case http.StatusOK:
    61  		return model.BaseMarketplacePluginsFromReader(resp.Body)
    62  	default:
    63  		return nil, errors.Errorf("failed with status code %d", resp.StatusCode)
    64  	}
    65  }
    66  
    67  func (c *Client) GetPlugin(filter *model.MarketplacePluginFilter, pluginVersion string) (*model.BaseMarketplacePlugin, error) {
    68  	plugins, err := c.GetPlugins(filter)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	for _, plugin := range plugins {
    73  		if plugin.Manifest.Version == pluginVersion {
    74  			return plugin, nil
    75  		}
    76  	}
    77  	return nil, errors.New("plugin not found")
    78  }
    79  
    80  // closeBody ensures the Body of an http.Response is properly closed.
    81  func closeBody(r *http.Response) {
    82  	if r.Body != nil {
    83  		_, _ = io.Copy(ioutil.Discard, r.Body)
    84  		_ = r.Body.Close()
    85  	}
    86  }
    87  
    88  func (c *Client) buildURL(urlPath string, args ...interface{}) string {
    89  	return fmt.Sprintf("%s/%s", strings.TrimRight(c.address, "/"), strings.TrimLeft(fmt.Sprintf(urlPath, args...), "/"))
    90  }
    91  
    92  func (c *Client) doGet(u string) (*http.Response, error) {
    93  	return c.httpClient.Get(u)
    94  }