| /* |
| Copyright 2017 Google Inc. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| package adapter |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "net/http" |
| "sync" |
| "time" |
| |
| "github.com/apid/istioApigeeAdapter/common" |
| ) |
| |
| const ( |
| defaultProductsFetch = time.Minute |
| ) |
| |
| type productManager struct { |
| fetchURL string |
| products map[string]*common.APIProduct |
| refresh time.Duration |
| expiration time.Time |
| latch *sync.Mutex |
| } |
| |
| func newProductManager(fetchURL string, refreshTime time.Duration) *productManager { |
| return &productManager{ |
| fetchURL: fetchURL, |
| refresh: refreshTime, |
| latch: &sync.Mutex{}, |
| } |
| } |
| |
| /* |
| getProducts returns the products that match a list of names. For now it is simple -- we will |
| use a mutex and update the list when it's expired. In the future we can be fancier with |
| periodic refresh. |
| */ |
| func (m *productManager) getProducts(names []string) ([]common.APIProduct, error) { |
| m.latch.Lock() |
| defer m.latch.Unlock() |
| |
| if m.products == nil || m.expiration.Before(time.Now()) { |
| err := m.fetchProductList() |
| if err != nil { |
| return nil, err |
| } |
| } |
| |
| var products []common.APIProduct |
| for _, name := range names { |
| p := m.products[name] |
| if p != nil { |
| products = append(products, *p) |
| } |
| } |
| return products, nil |
| } |
| |
| func (m *productManager) fetchProductList() error { |
| resp, err := http.Get(m.fetchURL) |
| if err != nil { |
| return err |
| } |
| defer resp.Body.Close() |
| if resp.StatusCode != 200 { |
| return fmt.Errorf("HTTP error %d fetching API product list", resp.StatusCode) |
| } |
| |
| var pl common.APIProductResponse |
| jr := json.NewDecoder(resp.Body) |
| err = jr.Decode(&pl) |
| if err != nil { |
| return err |
| } |
| |
| m.products = make(map[string]*common.APIProduct) |
| for _, p := range pl.Products { |
| m.products[p.Name] = &p |
| } |
| m.expiration = time.Now().Add(m.refresh) |
| return nil |
| } |