package ipfshttp import ( "encoding/json" "errors" "fmt" "time" "github.com/ipfs/ipfs-cluster/config" ma "github.com/multiformats/go-multiaddr" ) const configKey = "ipfshttp" // Default values for Config. const ( DefaultProxyAddr = "/ip4/127.0.0.1/tcp/9095" DefaultNodeAddr = "/ip4/127.0.0.1/tcp/5001" DefaultConnectSwarmsDelay = 7 * time.Second DefaultProxyReadTimeout = 10 * time.Minute DefaultProxyReadHeaderTimeout = 5 * time.Second DefaultProxyWriteTimeout = 10 * time.Minute DefaultProxyIdleTimeout = 60 * time.Second ) // Config is used to initialize a Connector and allows to customize // its behaviour. It implements the config.ComponentConfig interface. type Config struct { config.Saver // Listen parameters for the IPFS Proxy. Used by the IPFS // connector component. ProxyAddr ma.Multiaddr // Host/Port for the IPFS daemon. NodeAddr ma.Multiaddr // ConnectSwarmsDelay specifies how long to wait after startup before // attempting to open connections from this peer's IPFS daemon to the // IPFS daemons of other peers. ConnectSwarmsDelay time.Duration // Maximum duration before timing out reading a full request ProxyReadTimeout time.Duration // Maximum duration before timing out reading the headers of a request ProxyReadHeaderTimeout time.Duration // Maximum duration before timing out write of the response ProxyWriteTimeout time.Duration // Server-side amount of time a Keep-Alive connection will be // kept idle before being reused ProxyIdleTimeout time.Duration } type jsonConfig struct { ProxyListenMultiaddress string `json:"proxy_listen_multiaddress"` NodeMultiaddress string `json:"node_multiaddress"` ConnectSwarmsDelay string `json:"connect_swarms_delay"` ProxyReadTimeout string `json:"proxy_read_timeout"` ProxyReadHeaderTimeout string `json:"proxy_read_header_timeout"` ProxyWriteTimeout string `json:"proxy_write_timeout"` ProxyIdleTimeout string `json:"proxy_idle_timeout"` } // ConfigKey provides a human-friendly identifier for this type of Config. func (cfg *Config) ConfigKey() string { return configKey } // Default sets the fields of this Config to sensible default values. func (cfg *Config) Default() error { proxy, _ := ma.NewMultiaddr(DefaultProxyAddr) node, _ := ma.NewMultiaddr(DefaultNodeAddr) cfg.ProxyAddr = proxy cfg.NodeAddr = node cfg.ConnectSwarmsDelay = DefaultConnectSwarmsDelay cfg.ProxyReadTimeout = DefaultProxyReadTimeout cfg.ProxyReadHeaderTimeout = DefaultProxyReadHeaderTimeout cfg.ProxyWriteTimeout = DefaultProxyWriteTimeout cfg.ProxyIdleTimeout = DefaultProxyIdleTimeout return nil } // Validate checks that the fields of this Config have sensible values, // at least in appearance. func (cfg *Config) Validate() error { if cfg.ProxyAddr == nil { return errors.New("ipfshttp.proxy_listen_multiaddress not set") } if cfg.NodeAddr == nil { return errors.New("ipfshttp.node_multiaddress not set") } if cfg.ConnectSwarmsDelay < 0 { return errors.New("ipfshttp.connect_swarms_delay is invalid") } if cfg.ProxyReadTimeout <= 0 { return errors.New("ipfshttp.proxy_read_timeout is invalid") } if cfg.ProxyReadHeaderTimeout <= 0 { return errors.New("ipfshttp.proxy_read_header_timeout is invalid") } if cfg.ProxyWriteTimeout <= 0 { return errors.New("ipfshttp.proxy_write_timeout is invalid") } if cfg.ProxyIdleTimeout <= 0 { return errors.New("ipfshttp.proxy_idle_timeout invalid") } return nil } // LoadJSON parses a JSON representation of this Config as generated by ToJSON. func (cfg *Config) LoadJSON(raw []byte) error { jcfg := &jsonConfig{} err := json.Unmarshal(raw, jcfg) if err != nil { logger.Error("Error unmarshaling ipfshttp config") return err } proxyAddr, err := ma.NewMultiaddr(jcfg.ProxyListenMultiaddress) if err != nil { return fmt.Errorf("error parsing ipfs_proxy_listen_multiaddress: %s", err) } nodeAddr, err := ma.NewMultiaddr(jcfg.NodeMultiaddress) if err != nil { return fmt.Errorf("error parsing ipfs_node_multiaddress: %s", err) } cfg.ProxyAddr = proxyAddr cfg.NodeAddr = nodeAddr // errors ignored as Validate() below will catch them t, _ := time.ParseDuration(jcfg.ProxyReadTimeout) cfg.ProxyReadTimeout = t t, _ = time.ParseDuration(jcfg.ProxyReadHeaderTimeout) cfg.ProxyReadHeaderTimeout = t t, _ = time.ParseDuration(jcfg.ProxyWriteTimeout) cfg.ProxyWriteTimeout = t t, _ = time.ParseDuration(jcfg.ProxyIdleTimeout) cfg.ProxyIdleTimeout = t t, _ = time.ParseDuration(jcfg.ConnectSwarmsDelay) cfg.ConnectSwarmsDelay = t return cfg.Validate() } // ToJSON generates a human-friendly JSON representation of this Config. func (cfg *Config) ToJSON() (raw []byte, err error) { // Multiaddress String() may panic defer func() { if r := recover(); r != nil { err = fmt.Errorf("%s", r) } }() jcfg := &jsonConfig{} // Set all configuration fields jcfg.ProxyListenMultiaddress = cfg.ProxyAddr.String() jcfg.NodeMultiaddress = cfg.NodeAddr.String() jcfg.ProxyReadTimeout = cfg.ProxyReadTimeout.String() jcfg.ProxyReadHeaderTimeout = cfg.ProxyReadHeaderTimeout.String() jcfg.ProxyWriteTimeout = cfg.ProxyWriteTimeout.String() jcfg.ProxyIdleTimeout = cfg.ProxyIdleTimeout.String() jcfg.ConnectSwarmsDelay = cfg.ConnectSwarmsDelay.String() raw, err = config.DefaultJSONMarshal(jcfg) return }