github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/config/api.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/qri-io/jsonschema"
     8  )
     9  
    10  var (
    11  	// DefaultAPIPort is the port the webapp serves on by default
    12  	DefaultAPIPort = "2503"
    13  	// DefaultAPIAddress is the multaddr address the webapp serves on by default
    14  	DefaultAPIAddress = fmt.Sprintf("/ip4/127.0.0.1/tcp/%s", DefaultAPIPort)
    15  )
    16  
    17  // API holds configuration for the qri JSON api
    18  type API struct {
    19  	// APIAddress specifies the multiaddress to listen for JSON API calls
    20  	Address string `json:"address"`
    21  	// should this node have an API? default is true.
    22  	Enabled bool `json:"enabled"`
    23  	// support CORS signing from a list of origins
    24  	AllowedOrigins []string `json:"allowedorigins"`
    25  	// whether to allow requests from addresses other than localhost
    26  	ServeRemoteTraffic bool `json:"serveremotetraffic"`
    27  	// should the api provide the /webui endpoint? default is true
    28  	Webui bool `json:"webui"`
    29  }
    30  
    31  // SetArbitrary is an interface implementation of base/fill/struct in order to
    32  // safely consume config files that have definitions beyond those specified in
    33  // the struct. This simply ignores all additional fields at read time.
    34  func (a *API) SetArbitrary(key string, val interface{}) error {
    35  	return nil
    36  }
    37  
    38  // Validate validates all fields of api returning all errors found.
    39  func (a API) Validate() error {
    40  	schema := jsonschema.Must(`{
    41      "$schema": "http://json-schema.org/draft-06/schema#",
    42      "title": "api",
    43      "description": "Config for the api",
    44      "type": "object",
    45      "required": ["enabled", "address", "allowedorigins", "serveremotetraffic"],
    46      "properties": {
    47        "enabled": {
    48          "description": "When false, the api port does not listen for calls",
    49          "type": "boolean"
    50        },
    51        "address": {
    52          "description": "The address on which to listen for JSON API calls",
    53          "type": "string"
    54        },
    55        "webui": {
    56          "description": "when true the /webui endpoint will serve a frontend app",
    57          "type": "boolean"
    58        },
    59        "serveremotetraffic": {
    60          "description": "whether to allow requests from addresses other than localhost",
    61          "type": "boolean"
    62        },
    63        "allowedorigins": {
    64          "description": "Support CORS signing from a list of origins",
    65          "type": "array",
    66          "items": {
    67            "type": "string"
    68          }
    69        }
    70      }
    71    }`)
    72  	return validate(schema, &a)
    73  }
    74  
    75  // DefaultAPI returns the default configuration details
    76  func DefaultAPI() *API {
    77  	return &API{
    78  		Enabled: true,
    79  		Address: DefaultAPIAddress,
    80  		AllowedOrigins: []string{
    81  			fmt.Sprintf("http://localhost:%s", DefaultAPIPort),
    82  		},
    83  		Webui: true,
    84  	}
    85  }
    86  
    87  // Copy returns a deep copy of an API struct
    88  func (a *API) Copy() *API {
    89  	res := &API{
    90  		Enabled:            a.Enabled,
    91  		Address:            a.Address,
    92  		ServeRemoteTraffic: a.ServeRemoteTraffic,
    93  		Webui:              a.Webui,
    94  	}
    95  	if a.AllowedOrigins != nil {
    96  		res.AllowedOrigins = make([]string, len(a.AllowedOrigins))
    97  		reflect.Copy(reflect.ValueOf(res.AllowedOrigins), reflect.ValueOf(a.AllowedOrigins))
    98  	}
    99  	return res
   100  }