Merge pull request #641 from ipfs/tests/update-sharness-configs

Sharness: update configuration files used in sharness
This commit is contained in:
Hector Sanjuan 2019-01-14 12:08:08 +01:00 committed by GitHub
commit 935d9840b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 329 additions and 45 deletions

View File

@ -6,10 +6,12 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net/http"
"path/filepath" "path/filepath"
"time" "time"
"github.com/ipfs/ipfs-cluster/config" "github.com/ipfs/ipfs-cluster/config"
"github.com/rs/cors"
"github.com/kelseyhightower/envconfig" "github.com/kelseyhightower/envconfig"
@ -32,11 +34,26 @@ const (
// These are the default values for Config. // These are the default values for Config.
var ( var (
DefaultHeaders = map[string][]string{ DefaultHeaders = map[string][]string{}
"Access-Control-Allow-Headers": []string{"X-Requested-With", "Range"}, )
"Access-Control-Allow-Methods": []string{"GET"},
"Access-Control-Allow-Origin": []string{"*"}, // CORS defaults
var (
DefaultCORSAllowedOrigins = []string{"*"}
DefaultCORSAllowedMethods = []string{
http.MethodGet,
} }
// rs/cors this will set sensible defaults when empty:
// {"Origin", "Accept", "Content-Type", "X-Requested-With"}
DefaultCORSAllowedHeaders = []string{}
DefaultCORSExposedHeaders = []string{
"Content-Type",
"X-Stream-Output",
"X-Chunked-Output",
"X-Content-Length",
}
DefaultCORSAllowCredentials = true
DefaultCORSMaxAge time.Duration // 0. Means always.
) )
// Config is used to intialize the API object and allows to // Config is used to intialize the API object and allows to
@ -85,8 +102,16 @@ type Config struct {
BasicAuthCreds map[string]string BasicAuthCreds map[string]string
// Headers provides customization for the headers returned // Headers provides customization for the headers returned
// by the API. By default it sets a CORS policy. // by the API on existing routes.
Headers map[string][]string Headers map[string][]string
// CORS header management
CORSAllowedOrigins []string
CORSAllowedMethods []string
CORSAllowedHeaders []string
CORSExposedHeaders []string
CORSAllowCredentials bool
CORSMaxAge time.Duration
} }
type jsonConfig struct { type jsonConfig struct {
@ -105,6 +130,13 @@ type jsonConfig struct {
BasicAuthCreds map[string]string `json:"basic_auth_credentials"` BasicAuthCreds map[string]string `json:"basic_auth_credentials"`
Headers map[string][]string `json:"headers"` Headers map[string][]string `json:"headers"`
CORSAllowedOrigins []string `json:"cors_allowed_origins"`
CORSAllowedMethods []string `json:"cors_allowed_methods"`
CORSAllowedHeaders []string `json:"cors_allowed_headers"`
CORSExposedHeaders []string `json:"cors_exposed_headers"`
CORSAllowCredentials bool `json:"cors_allow_credentials"`
CORSMaxAge string `json:"cors_max_age"`
} }
// ConfigKey returns a human-friendly identifier for this type of // ConfigKey returns a human-friendly identifier for this type of
@ -136,6 +168,13 @@ func (cfg *Config) Default() error {
// Headers // Headers
cfg.Headers = DefaultHeaders cfg.Headers = DefaultHeaders
cfg.CORSAllowedOrigins = DefaultCORSAllowedOrigins
cfg.CORSAllowedMethods = DefaultCORSAllowedMethods
cfg.CORSAllowedHeaders = DefaultCORSAllowedHeaders
cfg.CORSExposedHeaders = DefaultCORSExposedHeaders
cfg.CORSAllowCredentials = DefaultCORSAllowCredentials
cfg.CORSMaxAge = DefaultCORSMaxAge
return nil return nil
} }
@ -154,7 +193,9 @@ func (cfg *Config) Validate() error {
case cfg.BasicAuthCreds != nil && len(cfg.BasicAuthCreds) == 0: case cfg.BasicAuthCreds != nil && len(cfg.BasicAuthCreds) == 0:
return errors.New("restapi.basic_auth_creds should be null or have at least one entry") return errors.New("restapi.basic_auth_creds should be null or have at least one entry")
case (cfg.pathSSLCertFile != "" || cfg.pathSSLKeyFile != "") && cfg.TLS == nil: case (cfg.pathSSLCertFile != "" || cfg.pathSSLKeyFile != "") && cfg.TLS == nil:
return errors.New("missing TLS configuration") return errors.New("restapi: missing TLS configuration")
case (cfg.CORSMaxAge < 0):
return errors.New("restapi.cors_max_age is invalid")
} }
return cfg.validateLibp2p() return cfg.validateLibp2p()
@ -232,12 +273,23 @@ func (cfg *Config) loadHTTPOptions(jcfg *jsonConfig) error {
return err return err
} }
// CORS
cfg.CORSAllowedOrigins = jcfg.CORSAllowedOrigins
cfg.CORSAllowedMethods = jcfg.CORSAllowedMethods
cfg.CORSAllowedHeaders = jcfg.CORSAllowedHeaders
cfg.CORSExposedHeaders = jcfg.CORSExposedHeaders
cfg.CORSAllowCredentials = jcfg.CORSAllowCredentials
if jcfg.CORSMaxAge == "" { // compatibility
jcfg.CORSMaxAge = "0s"
}
return config.ParseDurations( return config.ParseDurations(
"restapi", "restapi",
&config.DurationOpt{Duration: jcfg.ReadTimeout, Dst: &cfg.ReadTimeout, Name: "read_timeout"}, &config.DurationOpt{Duration: jcfg.ReadTimeout, Dst: &cfg.ReadTimeout, Name: "read_timeout"},
&config.DurationOpt{Duration: jcfg.ReadHeaderTimeout, Dst: &cfg.ReadHeaderTimeout, Name: "read_header_timeout"}, &config.DurationOpt{Duration: jcfg.ReadHeaderTimeout, Dst: &cfg.ReadHeaderTimeout, Name: "read_header_timeout"},
&config.DurationOpt{Duration: jcfg.WriteTimeout, Dst: &cfg.WriteTimeout, Name: "write_timeout"}, &config.DurationOpt{Duration: jcfg.WriteTimeout, Dst: &cfg.WriteTimeout, Name: "write_timeout"},
&config.DurationOpt{Duration: jcfg.IdleTimeout, Dst: &cfg.IdleTimeout, Name: "idle_timeout"}, &config.DurationOpt{Duration: jcfg.IdleTimeout, Dst: &cfg.IdleTimeout, Name: "idle_timeout"},
&config.DurationOpt{Duration: jcfg.CORSMaxAge, Dst: &cfg.CORSMaxAge, Name: "cors_max_age"},
) )
} }
@ -323,6 +375,12 @@ func (cfg *Config) ToJSON() (raw []byte, err error) {
IdleTimeout: cfg.IdleTimeout.String(), IdleTimeout: cfg.IdleTimeout.String(),
BasicAuthCreds: cfg.BasicAuthCreds, BasicAuthCreds: cfg.BasicAuthCreds,
Headers: cfg.Headers, Headers: cfg.Headers,
CORSAllowedOrigins: cfg.CORSAllowedOrigins,
CORSAllowedMethods: cfg.CORSAllowedMethods,
CORSAllowedHeaders: cfg.CORSAllowedHeaders,
CORSExposedHeaders: cfg.CORSExposedHeaders,
CORSAllowCredentials: cfg.CORSAllowCredentials,
CORSMaxAge: cfg.CORSMaxAge.String(),
} }
if cfg.ID != "" { if cfg.ID != "" {
@ -343,6 +401,20 @@ func (cfg *Config) ToJSON() (raw []byte, err error) {
return return
} }
func (cfg *Config) corsOptions() *cors.Options {
maxAgeSeconds := int(cfg.CORSMaxAge / time.Second)
return &cors.Options{
AllowedOrigins: cfg.CORSAllowedOrigins,
AllowedMethods: cfg.CORSAllowedMethods,
AllowedHeaders: cfg.CORSAllowedHeaders,
ExposedHeaders: cfg.CORSExposedHeaders,
AllowCredentials: cfg.CORSAllowCredentials,
MaxAge: maxAgeSeconds,
Debug: false,
}
}
func newTLSConfig(certFile, keyFile string) (*tls.Config, error) { func newTLSConfig(certFile, keyFile string) (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile) cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil { if err != nil {

View File

@ -13,14 +13,20 @@ import (
var cfgJSON = []byte(` var cfgJSON = []byte(`
{ {
"listen_multiaddress": "/ip4/127.0.0.1/tcp/9094", "listen_multiaddress": "/ip4/127.0.0.1/tcp/12122",
"ssl_cert_file": "test/server.crt", "ssl_cert_file": "test/server.crt",
"ssl_key_file": "test/server.key", "ssl_key_file": "test/server.key",
"read_timeout": "30s", "read_timeout": "30s",
"read_header_timeout": "5s", "read_header_timeout": "5s",
"write_timeout": "1m0s", "write_timeout": "1m0s",
"idle_timeout": "2m0s", "idle_timeout": "2m0s",
"basic_auth_credentials": null "basic_auth_credentials": null,
"cors_allowed_origins": ["myorigin"],
"cors_allowed_methods": ["GET"],
"cors_allowed_headers": ["X-Custom"],
"cors_exposed_headers": ["X-Chunked-Output"],
"cors_allow_credentials": false,
"cors_max_age": "1s"
} }
`) `)

View File

@ -21,6 +21,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/rs/cors"
"github.com/ipfs/ipfs-cluster/adder/adderutils" "github.com/ipfs/ipfs-cluster/adder/adderutils"
types "github.com/ipfs/ipfs-cluster/api" types "github.com/ipfs/ipfs-cluster/api"
@ -108,13 +110,20 @@ func NewAPIWithHost(cfg *Config, h host.Host) (*API, error) {
return nil, err return nil, err
} }
// Our handler is a gorilla router,
// wrapped with the cors handler,
// wrapped with the basic auth handler.
router := mux.NewRouter().StrictSlash(true) router := mux.NewRouter().StrictSlash(true)
handler := basicAuthHandler(
cfg.BasicAuthCreds,
cors.New(*cfg.corsOptions()).Handler(router),
)
s := &http.Server{ s := &http.Server{
ReadTimeout: cfg.ReadTimeout, ReadTimeout: cfg.ReadTimeout,
ReadHeaderTimeout: cfg.ReadHeaderTimeout, ReadHeaderTimeout: cfg.ReadHeaderTimeout,
WriteTimeout: cfg.WriteTimeout, WriteTimeout: cfg.WriteTimeout,
IdleTimeout: cfg.IdleTimeout, IdleTimeout: cfg.IdleTimeout,
Handler: router, Handler: handler,
} }
// See: https://github.com/ipfs/go-ipfs/issues/5168 // See: https://github.com/ipfs/go-ipfs/issues/5168
@ -225,9 +234,6 @@ func (api *API) Host() host.Host {
func (api *API) addRoutes(router *mux.Router) { func (api *API) addRoutes(router *mux.Router) {
for _, route := range api.routes() { for _, route := range api.routes() {
if api.config.BasicAuthCreds != nil {
route.HandlerFunc = basicAuth(route.HandlerFunc, api.config.BasicAuthCreds)
}
router. router.
Methods(route.Method). Methods(route.Method).
Path(route.Pattern). Path(route.Pattern).
@ -237,8 +243,13 @@ func (api *API) addRoutes(router *mux.Router) {
api.router = router api.router = router
} }
func basicAuth(h http.HandlerFunc, credentials map[string]string) http.HandlerFunc { // basicAuth wraps a given handler with basic authentication
return func(w http.ResponseWriter, r *http.Request) { func basicAuthHandler(credentials map[string]string, h http.Handler) http.Handler {
if credentials == nil {
return h
}
wrap := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
username, password, ok := r.BasicAuth() username, password, ok := r.BasicAuth()
if !ok { if !ok {
@ -268,6 +279,7 @@ func basicAuth(h http.HandlerFunc, credentials map[string]string) http.HandlerFu
} }
h.ServeHTTP(w, r) h.ServeHTTP(w, r)
} }
return http.HandlerFunc(wrap)
} }
func unauthorizedResp() (string, error) { func unauthorizedResp() (string, error) {

View File

@ -12,6 +12,7 @@ import (
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
"time"
"github.com/ipfs/ipfs-cluster/api" "github.com/ipfs/ipfs-cluster/api"
"github.com/ipfs/ipfs-cluster/test" "github.com/ipfs/ipfs-cluster/test"
@ -27,6 +28,7 @@ import (
const ( const (
SSLCertFile = "test/server.crt" SSLCertFile = "test/server.crt"
SSLKeyFile = "test/server.key" SSLKeyFile = "test/server.key"
clientOrigin = "myorigin"
) )
func testAPI(t *testing.T) *API { func testAPI(t *testing.T) *API {
@ -39,6 +41,10 @@ func testAPI(t *testing.T) *API {
cfg := &Config{} cfg := &Config{}
cfg.Default() cfg.Default()
cfg.HTTPListenAddr = apiMAddr cfg.HTTPListenAddr = apiMAddr
cfg.CORSAllowedOrigins = []string{clientOrigin}
cfg.CORSAllowedMethods = []string{"GET", "POST", "DELETE"}
//cfg.CORSAllowedHeaders = []string{"Content-Type"}
cfg.CORSMaxAge = 10 * time.Minute
rest, err := NewAPIWithHost(cfg, h) rest, err := NewAPIWithHost(cfg, h)
if err != nil { if err != nil {
@ -133,6 +139,10 @@ func checkHeaders(t *testing.T, rest *API, url string, headers http.Header) {
if headers.Get("Content-Type") != "application/json" { if headers.Get("Content-Type") != "application/json" {
t.Errorf("%s is not application/json", url) t.Errorf("%s is not application/json", url)
} }
if eh := headers.Get("Access-Control-Expose-Headers"); eh == "" {
t.Error("AC-Expose-Headers not set")
}
} }
// makes a libp2p host that knows how to talk to the rest API host. // makes a libp2p host that knows how to talk to the rest API host.
@ -194,7 +204,9 @@ func makeGet(t *testing.T, rest *API, url string, resp interface{}) {
h := makeHost(t, rest) h := makeHost(t, rest)
defer h.Close() defer h.Close()
c := httpClient(t, h, isHTTPS(url)) c := httpClient(t, h, isHTTPS(url))
httpResp, err := c.Get(url) req, _ := http.NewRequest(http.MethodGet, url, nil)
req.Header.Set("Origin", clientOrigin)
httpResp, err := c.Do(req)
processResp(t, httpResp, err, resp) processResp(t, httpResp, err, resp)
checkHeaders(t, rest, url, httpResp.Header) checkHeaders(t, rest, url, httpResp.Header)
} }
@ -207,7 +219,10 @@ func makePostWithContentType(t *testing.T, rest *API, url string, body []byte, c
h := makeHost(t, rest) h := makeHost(t, rest)
defer h.Close() defer h.Close()
c := httpClient(t, h, isHTTPS(url)) c := httpClient(t, h, isHTTPS(url))
httpResp, err := c.Post(url, contentType, bytes.NewReader(body)) req, _ := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
req.Header.Set("Content-Type", contentType)
req.Header.Set("Origin", clientOrigin)
httpResp, err := c.Do(req)
processResp(t, httpResp, err, resp) processResp(t, httpResp, err, resp)
checkHeaders(t, rest, url, httpResp.Header) checkHeaders(t, rest, url, httpResp.Header)
} }
@ -216,17 +231,32 @@ func makeDelete(t *testing.T, rest *API, url string, resp interface{}) {
h := makeHost(t, rest) h := makeHost(t, rest)
defer h.Close() defer h.Close()
c := httpClient(t, h, isHTTPS(url)) c := httpClient(t, h, isHTTPS(url))
req, _ := http.NewRequest("DELETE", url, bytes.NewReader([]byte{})) req, _ := http.NewRequest(http.MethodDelete, url, bytes.NewReader([]byte{}))
req.Header.Set("Origin", clientOrigin)
httpResp, err := c.Do(req) httpResp, err := c.Do(req)
processResp(t, httpResp, err, resp) processResp(t, httpResp, err, resp)
checkHeaders(t, rest, url, httpResp.Header) checkHeaders(t, rest, url, httpResp.Header)
} }
func makeOptions(t *testing.T, rest *API, url string, reqHeaders http.Header) http.Header {
h := makeHost(t, rest)
defer h.Close()
c := httpClient(t, h, isHTTPS(url))
req, _ := http.NewRequest(http.MethodOptions, url, nil)
req.Header = reqHeaders
httpResp, err := c.Do(req)
processResp(t, httpResp, err, nil)
return httpResp.Header
}
func makeStreamingPost(t *testing.T, rest *API, url string, body io.Reader, contentType string, resp interface{}) { func makeStreamingPost(t *testing.T, rest *API, url string, body io.Reader, contentType string, resp interface{}) {
h := makeHost(t, rest) h := makeHost(t, rest)
defer h.Close() defer h.Close()
c := httpClient(t, h, isHTTPS(url)) c := httpClient(t, h, isHTTPS(url))
httpResp, err := c.Post(url, contentType, body) req, _ := http.NewRequest(http.MethodPost, url, body)
req.Header.Set("Content-Type", contentType)
req.Header.Set("Origin", clientOrigin)
httpResp, err := c.Do(req)
processStreamingResp(t, httpResp, err, resp) processStreamingResp(t, httpResp, err, resp)
checkHeaders(t, rest, url, httpResp.Header) checkHeaders(t, rest, url, httpResp.Header)
} }
@ -825,3 +855,55 @@ func TestAPIRecoverAllEndpoint(t *testing.T) {
testBothEndpoints(t, tf) testBothEndpoints(t, tf)
} }
func TestCORS(t *testing.T) {
rest := testAPI(t)
defer rest.Shutdown()
type testcase struct {
method string
path string
}
tf := func(t *testing.T, url urlF) {
reqHeaders := make(http.Header)
reqHeaders.Set("Origin", "myorigin")
reqHeaders.Set("Access-Control-Request-Headers", "Content-Type")
for _, tc := range []testcase{
testcase{"GET", "/pins"},
// testcase{},
} {
reqHeaders.Set("Access-Control-Request-Method", tc.method)
headers := makeOptions(t, rest, url(rest)+tc.path, reqHeaders)
aorigin := headers.Get("Access-Control-Allow-Origin")
amethods := headers.Get("Access-Control-Allow-Methods")
aheaders := headers.Get("Access-Control-Allow-Headers")
acreds := headers.Get("Access-Control-Allow-Credentials")
maxage := headers.Get("Access-Control-Max-Age")
if aorigin != "myorigin" {
t.Error("Bad ACA-Origin:", aorigin)
}
if amethods != tc.method {
t.Error("Bad ACA-Methods:", amethods)
}
if aheaders != "Content-Type" {
t.Error("Bad ACA-Headers:", aheaders)
}
if acreds != "true" {
t.Error("Bad ACA-Credentials:", acreds)
}
if maxage != "600" {
t.Error("Bad AC-Max-Age:", maxage)
}
}
}
testBothEndpoints(t, tf)
}

View File

@ -155,6 +155,12 @@
"hash": "QmeP7Gybon3hs9KhoxSFvzqAHQS6xgyKYvsnjqktaXX3QN", "hash": "QmeP7Gybon3hs9KhoxSFvzqAHQS6xgyKYvsnjqktaXX3QN",
"name": "go-libp2p-pubsub", "name": "go-libp2p-pubsub",
"version": "100.11.9" "version": "100.11.9"
},
{
"author": "hsanjuan",
"hash": "QmNNk4iczWp8Q4R1mXQ2mrrjQvWisYqMqbW1an8qGbJZsM",
"name": "cors",
"version": "1.6.0"
} }
], ],
"gxVersion": "0.11.0", "gxVersion": "0.11.0",

View File

@ -24,10 +24,18 @@
} }
}, },
"api": { "api": {
"ipfsproxy": {
"listen_multiaddress": "/ip4/127.0.0.1/tcp/9095",
"node_multiaddress": "/ip4/127.0.0.1/tcp/5001",
"read_timeout": "10m0s",
"read_header_timeout": "5s",
"write_timeout": "10m0s",
"idle_timeout": "1m0s"
},
"restapi": { "restapi": {
"ssl_cert_file": "", "ssl_cert_file": "",
"ssl_key_file": "", "ssl_key_file": "",
"listen_multiaddress": "/ip4/127.0.0.1/tcp/9094", "http_listen_multiaddress": "/ip4/127.0.0.1/tcp/9094",
"read_timeout": "30s", "read_timeout": "30s",
"read_header_timeout": "5s", "read_header_timeout": "5s",
"write_timeout": "1m0s", "write_timeout": "1m0s",
@ -35,23 +43,50 @@
"basic_auth_credentials": { "basic_auth_credentials": {
"testuser": "testpass", "testuser": "testpass",
"userwithoutpass": "" "userwithoutpass": ""
} },
"cors_allowed_origins": [
"*"
],
"cors_allowed_methods": [
"GET"
],
"cors_allowed_headers": [],
"cors_exposed_headers": [
"Content-Type",
"X-Stream-Output",
"X-Chunked-Output",
"X-Content-Length"
],
"cors_allow_credentials": true,
"cors_max_age": "0s"
} }
}, },
"ipfs_connector": { "ipfs_connector": {
"ipfshttp": { "ipfshttp": {
"proxy_listen_multiaddress": "/ip4/127.0.0.1/tcp/9095",
"node_multiaddress": "/ip4/127.0.0.1/tcp/5001", "node_multiaddress": "/ip4/127.0.0.1/tcp/5001",
"connect_swarms_delay": "7s", "connect_swarms_delay": "30s",
"proxy_read_timeout": "10m0s", "pin_method": "refs",
"proxy_read_header_timeout": "5s", "ipfs_request_timeout": "5m0s",
"proxy_write_timeout": "10m0s", "pin_timeout": "24h0m0s",
"proxy_idle_timeout": "1m0s" "unpin_timeout": "3h0m0s"
}
},
"pin_tracker": {
"maptracker": {
"max_pin_queue_size": 50000,
"concurrent_pins": 10
},
"stateless": {
"max_pin_queue_size": 50000,
"concurrent_pins": 10
} }
}, },
"monitor": { "monitor": {
"monbasic": { "monbasic": {
"check_interval": "15s" "check_interval": "15s"
},
"pubsubmon": {
"check_interval": "15s"
} }
}, },
"informer": { "informer": {

View File

@ -24,10 +24,18 @@
} }
}, },
"api": { "api": {
"ipfsproxy": {
"listen_multiaddress": "/ip4/127.0.0.1/tcp/9095",
"node_multiaddress": "/ip4/127.0.0.1/tcp/5001",
"read_timeout": "10m0s",
"read_header_timeout": "5s",
"write_timeout": "10m0s",
"idle_timeout": "1m0s"
},
"restapi": { "restapi": {
"ssl_cert_file": "server.crt", "ssl_cert_file": "server.crt",
"ssl_key_file": "server.key", "ssl_key_file": "server.key",
"listen_multiaddress": "/ip4/127.0.0.1/tcp/9094", "http_listen_multiaddress": "/ip4/127.0.0.1/tcp/9094",
"read_timeout": "30s", "read_timeout": "30s",
"read_header_timeout": "5s", "read_header_timeout": "5s",
"write_timeout": "1m0s", "write_timeout": "1m0s",
@ -35,23 +43,50 @@
"basic_auth_credentials": { "basic_auth_credentials": {
"testuser": "testpass", "testuser": "testpass",
"userwithoutpass": "" "userwithoutpass": ""
} },
"cors_allowed_origins": [
"*"
],
"cors_allowed_methods": [
"GET"
],
"cors_allowed_headers": [],
"cors_exposed_headers": [
"Content-Type",
"X-Stream-Output",
"X-Chunked-Output",
"X-Content-Length"
],
"cors_allow_credentials": true,
"cors_max_age": "0s"
} }
}, },
"ipfs_connector": { "ipfs_connector": {
"ipfshttp": { "ipfshttp": {
"proxy_listen_multiaddress": "/ip4/127.0.0.1/tcp/9095",
"node_multiaddress": "/ip4/127.0.0.1/tcp/5001", "node_multiaddress": "/ip4/127.0.0.1/tcp/5001",
"connect_swarms_delay": "7s", "connect_swarms_delay": "30s",
"proxy_read_timeout": "10m0s", "pin_method": "refs",
"proxy_read_header_timeout": "5s", "ipfs_request_timeout": "5m0s",
"proxy_write_timeout": "10m0s", "pin_timeout": "24h0m0s",
"proxy_idle_timeout": "1m0s" "unpin_timeout": "3h0m0s"
}
},
"pin_tracker": {
"maptracker": {
"max_pin_queue_size": 50000,
"concurrent_pins": 10
},
"stateless": {
"max_pin_queue_size": 50000,
"concurrent_pins": 10
} }
}, },
"monitor": { "monitor": {
"monbasic": { "monbasic": {
"check_interval": "15s" "check_interval": "15s"
},
"pubsubmon": {
"check_interval": "15s"
} }
}, },
"informer": { "informer": {

View File

@ -24,30 +24,66 @@
} }
}, },
"api": { "api": {
"ipfsproxy": {
"listen_multiaddress": "/ip4/127.0.0.1/tcp/9095",
"node_multiaddress": "/ip4/127.0.0.1/tcp/5001",
"read_timeout": "10m0s",
"read_header_timeout": "5s",
"write_timeout": "10m0s",
"idle_timeout": "1m0s"
},
"restapi": { "restapi": {
"ssl_cert_file": "server.crt", "ssl_cert_file": "server.crt",
"ssl_key_file": "server.key", "ssl_key_file": "server.key",
"listen_multiaddress": "/ip4/127.0.0.1/tcp/9094", "http_listen_multiaddress": "/ip4/127.0.0.1/tcp/9094",
"read_timeout": "30s", "read_timeout": "30s",
"read_header_timeout": "5s", "read_header_timeout": "5s",
"write_timeout": "1m0s", "write_timeout": "1m0s",
"idle_timeout": "2m0s" "idle_timeout": "2m0s",
"basic_auth_credentials": null,
"cors_allowed_origins": [
"*"
],
"cors_allowed_methods": [
"GET"
],
"cors_allowed_headers": [],
"cors_exposed_headers": [
"Content-Type",
"X-Stream-Output",
"X-Chunked-Output",
"X-Content-Length"
],
"cors_allow_credentials": true,
"cors_max_age": "0s"
} }
}, },
"ipfs_connector": { "ipfs_connector": {
"ipfshttp": { "ipfshttp": {
"proxy_listen_multiaddress": "/ip4/127.0.0.1/tcp/9095",
"node_multiaddress": "/ip4/127.0.0.1/tcp/5001", "node_multiaddress": "/ip4/127.0.0.1/tcp/5001",
"connect_swarms_delay": "7s", "connect_swarms_delay": "30s",
"proxy_read_timeout": "10m0s", "pin_method": "refs",
"proxy_read_header_timeout": "5s", "ipfs_request_timeout": "5m0s",
"proxy_write_timeout": "10m0s", "pin_timeout": "24h0m0s",
"proxy_idle_timeout": "1m0s" "unpin_timeout": "3h0m0s"
}
},
"pin_tracker": {
"maptracker": {
"max_pin_queue_size": 50000,
"concurrent_pins": 10
},
"stateless": {
"max_pin_queue_size": 50000,
"concurrent_pins": 10
} }
}, },
"monitor": { "monitor": {
"monbasic": { "monbasic": {
"check_interval": "15s" "check_interval": "15s"
},
"pubsubmon": {
"check_interval": "15s"
} }
}, },
"informer": { "informer": {