github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/updater/sources/remote.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package sources
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"io"
    10  	"net/http"
    11  	"time"
    12  
    13  	"github.com/keybase/client/go/updater"
    14  	"github.com/keybase/client/go/updater/util"
    15  )
    16  
    17  // RemoteUpdateSource finds releases/updates from custom url feed (used primarily for testing)
    18  type RemoteUpdateSource struct {
    19  	defaultURI string
    20  	log        Log
    21  }
    22  
    23  // NewRemoteUpdateSource builds remote update source without defaults. The url used is passed
    24  // via options instead.
    25  func NewRemoteUpdateSource(defaultURI string, log Log) RemoteUpdateSource {
    26  	return RemoteUpdateSource{
    27  		defaultURI: defaultURI,
    28  		log:        log,
    29  	}
    30  }
    31  
    32  // Description returns update source description
    33  func (r RemoteUpdateSource) Description() string {
    34  	return "Remote"
    35  }
    36  
    37  func (r RemoteUpdateSource) sourceURL(options updater.UpdateOptions) string {
    38  	params := util.JoinPredicate([]string{options.Platform, options.Env, options.Channel}, "-", func(s string) bool { return s != "" })
    39  	url := options.URL
    40  	if url == "" {
    41  		url = r.defaultURI
    42  	}
    43  	if params == "" {
    44  		return fmt.Sprintf("%s/update.json", url)
    45  	}
    46  	return fmt.Sprintf("%s/update-%s.json", url, params)
    47  }
    48  
    49  // FindUpdate returns update for options
    50  func (r RemoteUpdateSource) FindUpdate(options updater.UpdateOptions) (*updater.Update, error) {
    51  	sourceURL := r.sourceURL(options)
    52  	req, err := http.NewRequest("GET", sourceURL, nil)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	client := &http.Client{
    57  		Timeout: time.Minute,
    58  	}
    59  	r.log.Infof("Request %#v", sourceURL)
    60  	resp, err := client.Do(req)
    61  	defer util.DiscardAndCloseBodyIgnoreError(resp)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	if resp.StatusCode != http.StatusOK {
    67  		err = fmt.Errorf("Updater remote returned bad status %v", resp.Status)
    68  		return nil, err
    69  	}
    70  
    71  	var reader io.Reader = resp.Body
    72  	var update updater.Update
    73  	if err = json.NewDecoder(reader).Decode(&update); err != nil {
    74  		return nil, fmt.Errorf("Bad updater remote response %s", err)
    75  	}
    76  
    77  	r.log.Debugf("Received update response: %#v", update)
    78  	return &update, nil
    79  }