generated from ipfs/ipfs-repository-template
-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: example proxy gatewya to ?format=raw & ?format=ipns-record
- Loading branch information
Showing
10 changed files
with
462 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Proxy Gateway | ||
|
||
This is an example that shows how to build a Gateway backed by the contents | ||
of another gateway. In this example, we implement two major structures: | ||
|
||
- [Block Store](./blockstore.go), which forwards the block requests to the backend | ||
gateway using `?format=raw`, and | ||
- [Routing System](./routing.go), which forwards the IPNS requests to the backend | ||
gateway using `?format=ipns-record`. In addition, DNSLink lookups are done locally. | ||
|
||
## Build | ||
|
||
```bash | ||
> go build -o proxy | ||
``` | ||
|
||
## Usage | ||
|
||
First, you need a compliant gateway that supports both RAW and IPNS Record response | ||
types. Once you have it, run the proxy gateway with its address as the host parameter: | ||
|
||
|
||
``` | ||
./proxy -h ipfs.io -p 8040 | ||
``` | ||
|
||
Now you can access the gateway in [127.0.0.1:8040](http://127.0.0.1:8040). It will | ||
behave like a regular IPFS 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
|
||
"github.com/ipfs/go-cid" | ||
blockstore "github.com/ipfs/go-ipfs-blockstore" | ||
"github.com/ipfs/go-libipfs/blocks" | ||
) | ||
|
||
var ( | ||
errNotImplemented = errors.New("not implemented") | ||
) | ||
|
||
type proxyStore struct { | ||
httpClient *http.Client | ||
host string | ||
validate bool | ||
} | ||
|
||
func newProxyStore(host string, client *http.Client) blockstore.Blockstore { | ||
if client == nil { | ||
client = http.DefaultClient | ||
} | ||
|
||
return &proxyStore{ | ||
host: host, | ||
httpClient: client, | ||
} | ||
} | ||
|
||
func (ps *proxyStore) fetch(ctx context.Context, c cid.Cid) (blocks.Block, error) { | ||
u, err := url.Parse(fmt.Sprintf("http://%s/ipfs/%s?format=raw", ps.host, c)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
resp, err := ps.httpClient.Do(&http.Request{ | ||
Method: http.MethodGet, | ||
URL: u, | ||
Header: http.Header{ | ||
"Accept": []string{"application/vnd.ipld.raw"}, | ||
}, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer resp.Body.Close() | ||
rb, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if ps.validate { | ||
nc, err := c.Prefix().Sum(rb) | ||
if err != nil { | ||
return nil, blocks.ErrWrongHash | ||
} | ||
if !nc.Equals(c) { | ||
fmt.Printf("got %s vs %s\n", nc, c) | ||
return nil, blocks.ErrWrongHash | ||
} | ||
} | ||
return blocks.NewBlockWithCid(rb, c) | ||
} | ||
|
||
func (ps *proxyStore) Has(ctx context.Context, c cid.Cid) (bool, error) { | ||
blk, err := ps.fetch(ctx, c) | ||
if err != nil { | ||
return false, err | ||
} | ||
return blk != nil, nil | ||
} | ||
|
||
func (ps *proxyStore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) { | ||
blk, err := ps.fetch(ctx, c) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return blk, nil | ||
} | ||
|
||
func (ps *proxyStore) GetSize(ctx context.Context, c cid.Cid) (int, error) { | ||
blk, err := ps.fetch(ctx, c) | ||
if err != nil { | ||
return 0, err | ||
} | ||
return len(blk.RawData()), nil | ||
} | ||
|
||
func (ps *proxyStore) HashOnRead(enabled bool) { | ||
ps.validate = enabled | ||
} | ||
|
||
func (c *proxyStore) Put(context.Context, blocks.Block) error { | ||
return errNotImplemented | ||
} | ||
|
||
func (c *proxyStore) PutMany(context.Context, []blocks.Block) error { | ||
return errNotImplemented | ||
} | ||
func (c *proxyStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) { | ||
return nil, errNotImplemented | ||
} | ||
func (c *proxyStore) DeleteBlock(context.Context, cid.Cid) error { | ||
return errNotImplemented | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"log" | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/ipfs/go-blockservice" | ||
offline "github.com/ipfs/go-ipfs-exchange-offline" | ||
gw "github.com/ipfs/go-libipfs/examples/gateway" | ||
) | ||
|
||
func main() { | ||
hostPtr := flag.String("h", "", "hostname of gateway to proxy to") | ||
portPtr := flag.Int("p", 8080, "port to run this gateway from") | ||
flag.Parse() | ||
|
||
// Sets up the block store, which will proxy the block requests to the given gateway. | ||
blockStore := newProxyStore(*hostPtr, nil) | ||
blockService := blockservice.New(blockStore, offline.Exchange(blockStore)) | ||
|
||
// Sets up the routing system, which will proxy the IPNS routing requests to the given gateway. | ||
routing := newProxyRouting(*hostPtr, nil) | ||
|
||
// Creates the gateway with the block service and the routing. | ||
gateway, err := gw.NewBlocksGateway(blockService, routing) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
handler := gw.NewBlocksHandler(gateway, *portPtr) | ||
address := "127.0.0.1:" + strconv.Itoa(*portPtr) | ||
log.Printf("Listening on http://%s", address) | ||
|
||
if err := http.ListenAndServe(address, handler); err != nil { | ||
log.Fatal(err) | ||
} | ||
} |
Oops, something went wrong.