diff --git a/examples/gateway/car/README.md b/examples/gateway/car/README.md index 4d41341fc..2fea3fa66 100644 --- a/examples/gateway/car/README.md +++ b/examples/gateway/car/README.md @@ -1,4 +1,4 @@ -# Gateway backed by a CAR File +# HTTP Gateway backed by a CAR File This is an example that shows how to build a Gateway backed by the contents of a CAR file. A [CAR file](https://ipld.io/specs/transport/car/) is a Content @@ -7,7 +7,7 @@ Addressable aRchive that contains blocks. ## Build ```bash -> go build -o gateway +> go build -o car-gateway ``` ## Usage @@ -23,10 +23,19 @@ Then, you can start the gateway with: ``` -./gateway -c data.car -p 8040 +./car-gateway -c data.car -p 8040 ``` +### Subdomain gateway + Now you can access the gateway in [localhost:8040](http://localhost:8040). It will -behave like a regular IPFS Gateway, except for the fact that all contents are provided +behave like a regular [Subdomain IPFS Gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway), +except for the fact that all contents are provided from the CAR file. Therefore, things such as IPNS resolution and fetching contents from nodes in the IPFS network won't work. + +### Path gateway + +If you don't need Origin isolation and only care about hosting flat files, +a plain [path gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#path-gateway) at [127.0.0.1:8040](http://127.0.0.1:8040) +may suffice. diff --git a/examples/gateway/car/main.go b/examples/gateway/car/main.go index 2c1918d72..070dacb94 100644 --- a/examples/gateway/car/main.go +++ b/examples/gateway/car/main.go @@ -18,7 +18,7 @@ import ( func main() { carFilePtr := flag.String("c", "", "path to CAR file to back this gateway from") - portPtr := flag.Int("p", 8080, "port to run this gateway from") + port := flag.Int("p", 8040, "port to run this gateway from") flag.Parse() blockService, roots, f, err := newBlockServiceFromCAR(*carFilePtr) @@ -31,28 +31,35 @@ func main() { if err != nil { log.Fatal(err) } - handler := common.NewBlocksHandler(gwAPI, *portPtr) + handler := common.NewBlocksHandler(gwAPI, *port) // Initialize the public gateways that we will want to have available through // Host header rewritting. This step is optional and only required if you're // running multiple public gateways and want different settings and support // for DNSLink and Subdomain Gateways. + noDNSLink := true // If you set DNSLink to point at the CID from CAR, you can load it! publicGateways := map[string]*gateway.Specification{ + // Support public requests with Host: CID.ipfs.example.net and ID.ipns.example.net + "example.net": { + Paths: []string{"/ipfs", "/ipns"}, + NoDNSLink: noDNSLink, + UseSubdomains: true, + }, + // Support local requests "localhost": { Paths: []string{"/ipfs", "/ipns"}, - NoDNSLink: true, + NoDNSLink: noDNSLink, UseSubdomains: true, }, } - noDNSLink := true handler = gateway.WithHostname(handler, gwAPI, publicGateways, noDNSLink) - log.Printf("Listening on http://localhost:%d", *portPtr) + log.Printf("Listening on http://localhost:%d", *port) for _, cid := range roots { - log.Printf("Hosting CAR root at http://localhost:%d/ipfs/%s", *portPtr, cid.String()) + log.Printf("Hosting CAR root at http://localhost:%d/ipfs/%s", *port, cid.String()) } - if err := http.ListenAndServe(":"+strconv.Itoa(*portPtr), handler); err != nil { + if err := http.ListenAndServe(":"+strconv.Itoa(*port), handler); err != nil { log.Fatal(err) } } diff --git a/examples/gateway/proxy/README.md b/examples/gateway/proxy/README.md index 604806360..4164aad1e 100644 --- a/examples/gateway/proxy/README.md +++ b/examples/gateway/proxy/README.md @@ -28,9 +28,31 @@ types. Once you have it, run the proxy gateway with its address as the host para ``` -./verifying-proxy -h https://ipfs.io -p 8040 +./verifying-proxy -g https://ipfs.io -p 8040 ``` +### Subdomain gateway + Now you can access the gateway in [localhost:8040](http://localhost:8040). It will -behave like a regular IPFS Gateway, except for the fact that it runs no libp2p, and has no local blockstore. +behave like a regular [Subdomain IPFS Gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway), +except for the fact that it runs no libp2p, and has no local blockstore. All contents are provided by a remote gateway and fetched as RAW Blocks and Records, and verified locally. + +### Path gateway + +If you don't need Origin isolation and only care about hosting flat files, +a plain [path gateway](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#path-gateway) at [127.0.0.1:8040](http://127.0.0.1:8040) +may suffice. + +### DNSLink gateway + +Gateway supports hosting of [DNSLink](https://dnslink.dev/) websites. All you need is to pass `Host` header with FQDN that has DNSLink set up: + +```console +$ curl -sH 'Host: en.wikipedia-on-ipfs.org' 'http://127.0.0.1:8080/wiki/' | head -3 + + + Wikipedia, the free encyclopedia +``` + +Put it behind a reverse proxy terminating TLS (like Nginx) and voila! diff --git a/examples/gateway/proxy/main.go b/examples/gateway/proxy/main.go index 5e99e61ba..6f9282c19 100644 --- a/examples/gateway/proxy/main.go +++ b/examples/gateway/proxy/main.go @@ -14,7 +14,7 @@ import ( func main() { gatewayUrlPtr := flag.String("g", "", "gateway to proxy to") - portPtr := flag.Int("p", 8080, "port to run this gateway from") + port := flag.Int("p", 8040, "port to run this gateway from") flag.Parse() // Sets up the block store, which will proxy the block requests to the given gateway. @@ -29,24 +29,31 @@ func main() { if err != nil { log.Fatal(err) } - handler := common.NewBlocksHandler(gwAPI, *portPtr) + handler := common.NewBlocksHandler(gwAPI, *port) // Initialize the public gateways that we will want to have available through // Host header rewritting. This step is optional and only required if you're // running multiple public gateways and want different settings and support // for DNSLink and Subdomain Gateways. + noDNSLink := false publicGateways := map[string]*gateway.Specification{ + // Support public requests with Host: CID.ipfs.example.net and ID.ipns.example.net + "example.net": { + Paths: []string{"/ipfs", "/ipns"}, + NoDNSLink: noDNSLink, + UseSubdomains: true, + }, + // Support local requests "localhost": { Paths: []string{"/ipfs", "/ipns"}, - NoDNSLink: true, + NoDNSLink: noDNSLink, UseSubdomains: true, }, } - noDNSLink := true handler = gateway.WithHostname(handler, gwAPI, publicGateways, noDNSLink) - log.Printf("Listening on http://localhost:%d", *portPtr) - if err := http.ListenAndServe(":"+strconv.Itoa(*portPtr), handler); err != nil { + log.Printf("Listening on http://localhost:%d", *port) + if err := http.ListenAndServe(":"+strconv.Itoa(*port), handler); err != nil { log.Fatal(err) } } diff --git a/gateway/hostname.go b/gateway/hostname.go index 61c0dc16c..563804e12 100644 --- a/gateway/hostname.go +++ b/gateway/hostname.go @@ -20,6 +20,7 @@ import ( type Specification struct { // Paths is explicit list of path prefixes that should be handled by // this gateway. Example: `["/ipfs", "/ipns"]` + // Useful if you only want to support immutable `/ipfs`. Paths []string // UseSubdomains indicates whether or not this gateway uses subdomains @@ -32,13 +33,17 @@ type Specification struct { // for security reasons (Origin isolation). UseSubdomains bool - // NoDNSLink configures this gateway to _not_ resolve DNSLink for the FQDN - // provided in `Host` HTTP header. + // NoDNSLink configures this gateway to _not_ resolve DNSLink for the + // specific FQDN provided in `Host` HTTP header. Useful when you want to + // explicitly allow or refuse hosting a single hostname. To refuse all + // DNSLinks in `Host` processing, pass noDNSLink to `WithHostname` instead. + // This flag overrides the global one. NoDNSLink bool // InlineDNSLink configures this gateway to always inline DNSLink names // (FQDN) into a single DNS label in order to interop with wildcard TLS certs // and Origin per CID isolation provided by rules like https://publicsuffix.org + // This should be set to true if you use HTTPS. InlineDNSLink bool }