diff --git a/core/corehttp/hostname.go b/core/corehttp/hostname.go index 8a251ea08f1..a8f28f2599c 100644 --- a/core/corehttp/hostname.go +++ b/core/corehttp/hostname.go @@ -18,12 +18,12 @@ import ( ) var pathGatewaySpec = config.GatewaySpec{ - PathPrefixes: []string{ipfsPathPrefix, ipnsPathPrefix, "/api/"}, + Paths: []string{ipfsPathPrefix, ipnsPathPrefix, "/api/"}, UseSubdomains: false, } var subdomainGatewaySpec = config.GatewaySpec{ - PathPrefixes: []string{ipfsPathPrefix, ipnsPathPrefix}, + Paths: []string{ipfsPathPrefix, ipnsPathPrefix}, UseSubdomains: true, } @@ -105,7 +105,7 @@ func HostnameOption() ServeOption { // the subdomain feature. // Does this gateway _handle_ this path? - if hasPrefix(r.URL.Path, gw.PathPrefixes...) { + if hasPrefix(r.URL.Path, gw.Paths...) { // It does. // Should this gateway use subdomains instead of paths? @@ -134,9 +134,16 @@ func HostnameOption() ServeOption { // Again, is this a known gateway that supports subdomains? if gw, ok := isKnownGateway(host); ok && gw.UseSubdomains { - // Yes, serve the request (and rewrite the path to not use subdomains). - r.URL.Path = pathPrefix + r.URL.Path - childMux.ServeHTTP(w, r) + // Does this gateway _handle_ this path? + if hasPrefix(pathPrefix, gw.Paths...) { + // It does. + // Yes, serve the request (and rewrite the path to not use subdomains). + r.URL.Path = pathPrefix + r.URL.Path + childMux.ServeHTTP(w, r) + return + } + // If not, finish with error + http.Error(w, "SubdomainGateway: requested path is not allowed", http.StatusForbidden) return } } @@ -147,14 +154,14 @@ func HostnameOption() ServeOption { if len(fqdn) > 0 && isd.IsDomain(fqdn) { gw, ok := isKnownGateway(fqdn) // Confirm DNSLink was not disabled for the fqdn or globally - enabled := (ok && !gw.NoDNSLink) || !cfg.Gateway.GatewaySpec.NoDNSLink + enabled := (ok && !gw.NoDNSLink) || !cfg.Gateway.NoDNSLink if enabled { name := "/ipns/" + fqdn _, err := n.Namesys.Resolve(ctx, name, nsopts.Depth(1)) if err == nil || err == namesys.ErrResolveRecursion { - // Check if this gateway has any PathPrefixes mounted - if ok && hasPrefix(r.URL.Path, gw.PathPrefixes...) { - // Yes: PathPrefixes should take priority over DNSLink + // Check if this gateway has any Paths mounted + if ok && hasPrefix(r.URL.Path, gw.Paths...) { + // Yes: Paths should take priority over DNSLink childMux.ServeHTTP(w, r) return } diff --git a/docs/config.md b/docs/config.md index 6ff508e2db6..a592a98366d 100644 --- a/docs/config.md +++ b/docs/config.md @@ -408,55 +408,46 @@ location /blog/ { Default: `[]` -- `NoDNSLink` - A boolean to configure whether DNSLink lookup for value in `Host` HTTP header should be performed. - If DNSLink is present, content path stored in it is mounted at `/` and respective payload is returned to the client. +- `NoDNSLink` + A boolean to configure whether DNSLink lookup for value in `Host` + HTTP header should be performed. If DNSLink is present, content path stored + in the DNS TXT record is mounted at `/` and respective payload is returned to + the client. - Default: `false` +Default: `false` ### Gateway.PublicGateways -`PublicGateways` is a dictionary for overriding default options on specific fully qualified domain names (FQDN). +`PublicGateways` is a dictionary for defining gateway behavior on specific fully qualified domain names (FQDN). Options for changing behavior per hostname: -- `NoDNSLink` - Overrides global setting of the same name. - Default: `false` -- `PathPrefixes` +- `Paths` Array of paths that should be mounted at the root of domain name. - **TODO: this does not override global 'PathPrefixes' used for validation of X-Ipfs-Gateway-Prefix header. Should this have different name? eg. PathMounts?** Example: `["/ipfs", "/ipns", "/api"]` - Default: `[]` - - **Note:** when both `PathPrefixes` and DNSLink are mounted, `PathPrefixes` take priority + - **Note:** when both `Paths` and DNSLink are mounted, `Paths` takes priority + - `UseSubdomains` A boolean to configure whether the gateway provides [Origin isolation](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) between content roots. Default: `false` - `true` – mount [subdomain gateway](#https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://{cid}.ipfs.{hostname}` + - requires respective `Paths` to be set - requests for `http://{hostname}/ipfs/{cid}` will return redirect to `http://{cid}.ipfs.{hostname}` - `false` – mount [path gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#path-gateway) at `http://{hostname}/ipfs/{cid}` - - **(not implemented yet)** due to the lack of Origin isolation, cookies and storage will be disabled by [Clear-Site-Data](https://github.com/ipfs/in-web-browsers/issues/157) header - + - **(not implemented yet)** due to the lack of Origin isolation, cookies and storage on `Paths` will be disabled by [Clear-Site-Data](https://github.com/ipfs/in-web-browsers/issues/157) header #### Examples of common use cases * Public [subdomain gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#subdomain-gateway) at `http://{cid}.ipfs.dweb.link` - ```json - "Gateway": { - "PublicGateways": { - "dweb.link": { - "UseSubdomains": true - ``` - Version that redirects content paths - to subdomains (`http://dweb.link/ipfs/{cid}`→`http://{cid}.ipfs.dweb.link`) for backward-compatibility: ```json "Gateway": { "PublicGateways": { "dweb.link": { "UseSubdomains": true, - "PathPrefixes": ["/ipfs", "/ipns"] + "Paths": ["/ipfs", "/ipns"] ``` - **TODO: should this backward-compatibility redirect be enabled by the default when `UseSubdomains: true`?** + **Note:** this enables automatic redirects from content paths to subdomains + `http://dweb.link/ipfs/{cid}` → `http://{cid}.ipfs.dweb.link` * Public [path gateway](https://docs-beta.ipfs.io/how-to/address-ipfs-on-web/#path-gateway) at `http://ipfs.io/ipfs/{cid}` ```json @@ -464,17 +455,17 @@ Options for changing behavior per hostname: "PublicGateways": { "ipfs.io": { "UseSubdomains": false, - "PathPrefixes": ["/ipfs", "/ipns", "/api"] + "Paths": ["/ipfs", "/ipns", "/api"] ``` -* Public [DNSLink](https://dnslink.io/) gateway (accepting every hostname passed in `Host` header) - is enabled by default: +* Public [DNSLink](https://dnslink.io/) gateway resolving every hostname passed in `Host` header + (this is the default, works out of the box): ```json "Gateway": { "NoDNSLink": false ``` -* Site-specific [DNSLink](https://dnslink.io/) gateway. +* Hardened, site-specific [DNSLink](https://dnslink.io/) gateway. Disabling public gateway by default (`NoFetch: true`), and enabling selected gateway features only on specific hostname for which data is already present on the node: @@ -485,9 +476,8 @@ Options for changing behavior per hostname: "PublicGateways": { "en.wikipedia-on-ipfs.org": { "NoDNSLink": false, - "PathPrefixes": [] + "Paths": [] ``` - **TODO: note how `Gateway.PublicGateways[host].PathPrefixes = []` has a different meaning than `Gateway.PathPrefixes = []`)** **Note:** Default entries for localhost name and loopback IPs are always present. User-provided config will be merged on top of implicit values: @@ -496,15 +486,15 @@ User-provided config will be merged on top of implicit values: "Gateway": { "PublicGateways": { "127.0.0.1": { - "PathPrefixes": ["/ipfs", "/ipns", "/api"], + "Paths": ["/ipfs", "/ipns", "/api"], "UseSubdomains": false }, "::1": { - "PathPrefixes": ["/ipfs", "/ipns", "/api"], + "Paths": ["/ipfs", "/ipns", "/api"], "UseSubdomains": false }, "localhost": { - "PathPrefixes": ["/ipfs", "ipns"], + "Paths": ["/ipfs", "ipns"], "UseSubdomains": true } } diff --git a/go.mod b/go.mod index 4dec6fb9571..5e727d42b66 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/ipfs/go-ipfs-blockstore v0.1.4 github.com/ipfs/go-ipfs-chunker v0.0.4 github.com/ipfs/go-ipfs-cmds v0.1.1 - github.com/ipfs/go-ipfs-config v0.2.1-0.20200124130635-a5ddb98579f9 + github.com/ipfs/go-ipfs-config v0.2.1-0.20200130123729-cc09b7a636a0 github.com/ipfs/go-ipfs-ds-help v0.1.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 github.com/ipfs/go-ipfs-exchange-offline v0.0.1 diff --git a/go.sum b/go.sum index 2a3598d40a0..7e5a59bd22b 100644 --- a/go.sum +++ b/go.sum @@ -239,6 +239,8 @@ github.com/ipfs/go-ipfs-config v0.2.1-0.20200110091747-69d023fb5309 h1:bMQ/X8L/X github.com/ipfs/go-ipfs-config v0.2.1-0.20200110091747-69d023fb5309/go.mod h1:vEXbHHFPMCGCVhgv8oye4QF75kQ/gyZ3/tBdMMZFAps= github.com/ipfs/go-ipfs-config v0.2.1-0.20200124130635-a5ddb98579f9 h1:xz9PPeI9gmkCN9yvQ6r/TV84jK47cxmG7BHmvjirHzI= github.com/ipfs/go-ipfs-config v0.2.1-0.20200124130635-a5ddb98579f9/go.mod h1:vEXbHHFPMCGCVhgv8oye4QF75kQ/gyZ3/tBdMMZFAps= +github.com/ipfs/go-ipfs-config v0.2.1-0.20200130123729-cc09b7a636a0 h1:UdvMiJ03PLcwp/ERaFnfQwbJYjaI73JjurdZ2LdCqOQ= +github.com/ipfs/go-ipfs-config v0.2.1-0.20200130123729-cc09b7a636a0/go.mod h1:vEXbHHFPMCGCVhgv8oye4QF75kQ/gyZ3/tBdMMZFAps= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ= github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=