Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Lars Gierth <larsg@systemli.org>
  • Loading branch information
Lars Gierth committed Sep 4, 2016
1 parent 847d056 commit 35c8b67
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 44 deletions.
48 changes: 42 additions & 6 deletions core/coreapi/coreapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,31 @@ package coreapi
import (
core "github.com/ipfs/go-ipfs/core"
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
importer "github.com/ipfs/go-ipfs/importer"
chunk "github.com/ipfs/go-ipfs/importer/chunk"
dag "github.com/ipfs/go-ipfs/merkledag"
path "github.com/ipfs/go-ipfs/path"
uio "github.com/ipfs/go-ipfs/unixfs/io"
mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
)

type Link struct {
name string
size uint64
hash mh.Multihash
}

func (l *Link) Name() string { return l.name }
func (l *Link) Size() uint64 { return l.size }
func (l *Link) Hash() mh.Multihash { return l.hash }

type CoreAPI struct {
ctx context.Context
node *core.IpfsNode
}

func NewCoreAPI(ctx context.Context, node *core.IpfsNode) (*CoreAPI, error) {
func NewCoreAPI(ctx context.Context, node *core.IpfsNode) (coreiface.CoreAPI, error) {
api := &CoreAPI{ctx: ctx, node: node}
return api, nil
}
Expand All @@ -27,8 +40,8 @@ func (api *CoreAPI) IpfsNode() *core.IpfsNode {
return api.node
}

func (api *CoreAPI) resolve(p string) (*dag.Node, error) {
dagnode, err := core.Resolve(api.ctx, api.node, path.Path(p))
func (api *CoreAPI) resolve(p coreiface.Path) (*dag.Node, error) {
dagnode, err := core.Resolve(api.ctx, api.node, p.(path.Path))
if err == core.ErrNoNamesys && !api.node.OnlineMode() {
return nil, coreiface.ErrOffline
} else if err != nil {
Expand All @@ -37,7 +50,12 @@ func (api *CoreAPI) resolve(p string) (*dag.Node, error) {
return dagnode, nil
}

func (api *CoreAPI) Cat(p string) (coreiface.Data, error) {
func (api *CoreAPI) Cat(p coreiface.Path) (coreiface.Data, error) {
// special case for the empty unixfs directory
if p.String() == "/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
return nil, coreiface.ErrDir
}

dagnode, err := api.resolve(p)
if err != nil {
return nil, err
Expand All @@ -51,14 +69,32 @@ func (api *CoreAPI) Cat(p string) (coreiface.Data, error) {
return r, nil
}

func (api *CoreAPI) Ls(p string) ([]coreiface.Link, error) {
func (api *CoreAPI) Ls(p coreiface.Path) ([]coreiface.Link, error) {
// special case for the empty unixfs directory
if p.String() == "/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
return make([]coreiface.Link, 0), nil
}

dagnode, err := api.resolve(p)
if err != nil {
return nil, err
}
links := make([]coreiface.Link, len(dagnode.Links))
for i, l := range dagnode.Links {
links[i] = coreiface.Link{Name: l.Name, Size: l.Size, Hash: l.Hash}
links[i] = &Link{l.Name, l.Size, l.Hash}
}
return links, nil
}

func (api *CoreAPI) Add(data coreiface.DataForAdd) (coreiface.Path, error) {
splitter := chunk.DefaultSplitter(data)
dagnode, err := importer.BuildDagFromReader(api.node.DAG, splitter)
if err != nil {
return path.Path(""), err
}
k, err := api.node.DAG.Add(dagnode)
if err != nil {
return path.Path(""), err
}
return path.Path("/ipfs/" + k.String()), nil
}
12 changes: 12 additions & 0 deletions core/coreapi/coreapi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package coreapi_test

import (
"testing"

coreapi "github.com/ipfs/go-ipfs/core/coreapi"
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
)

func TestImplementsInterface(t *testing.T) {

}
30 changes: 17 additions & 13 deletions core/coreapi/interface/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,36 @@ import (

core "github.com/ipfs/go-ipfs/core"

mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
mhash "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
)

type CoreAPI interface {
Context() context.Context
IpfsNode() *core.IpfsNode // XXX temporary
Cat(string) (Data, error)
Ls(string) ([]Link, error)
IpfsNode() *core.IpfsNode // XXX temporary
Cat(Path) (Data, error) // http GET
Ls(Path) ([]Link, error) // http GET
Add(DataForAdd) (Path, error) // http POST
}

type Object struct {
Links []Link
Data Data
type Path interface {
String() string
Segments() []string
}

type Link struct {
Name string // utf-8
Size uint64
Hash mh.Multihash
type Link interface {
Name() string
Size() uint64
Hash() mhash.Multihash
}

type DataForAdd interface {
io.ReadCloser
}

type Data interface {
io.Reader
DataForAdd
io.Seeker
io.Closer
}

var ErrDir = errors.New("object is a directory")
Expand Down
46 changes: 21 additions & 25 deletions core/corehttp/gateway_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,6 @@ func newGatewayHandler(api coreiface.CoreAPI, conf GatewayConfig) *gatewayHandle
return i
}

// TODO(cryptix): find these helpers somewhere else
func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.Node, error) {
// TODO(cryptix): change and remove this helper once PR1136 is merged
// return ufs.AddFromReader(i.api.IpfsNode(), r.Body)
return importer.BuildDagFromReader(
i.api.IpfsNode().DAG,
chunk.DefaultSplitter(r))
}

// TODO(btc): break this apart into separate handlers using a more expressive muxer
func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer func() {
Expand Down Expand Up @@ -154,7 +145,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
ipnsHostname = true
}

dr, err := i.api.Cat(urlPath)
dr, err := i.api.Cat(path.Path(urlPath))
dir := false
if err == coreiface.ErrOffline {
w.WriteHeader(http.StatusServiceUnavailable)
Expand Down Expand Up @@ -215,7 +206,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
return
}

links, err := i.api.Ls(urlPath)
links, err := i.api.Ls(path.Path(urlPath))
if err != nil {
internalWebError(w, err)
return
Expand All @@ -226,7 +217,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
// loop through files
foundIndex := false
for _, link := range links {
if link.Name == "index.html" {
if link.Name() == "index.html" {
log.Debugf("found index.html link for %s", urlPath)
foundIndex = true

Expand All @@ -238,7 +229,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
}

// return index page instead.
ir, err := i.api.Cat(urlPath + "/index.html")
ir, err := i.api.Cat(path.Path(urlPath + "/index.html"))
if err != nil {
internalWebError(w, err)
return
Expand All @@ -251,8 +242,11 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
}

// See comment above where originalUrlPath is declared.
di := directoryItem{humanize.Bytes(link.Size), link.Name, gopath.Join(originalUrlPath, link.Name)}
dirListing = append(dirListing, di)
dirListing = append(dirListing, directoryItem{
humanize.Bytes(link.Size()),
link.Name(),
gopath.Join(originalUrlPath, link.Name()),
})
}

if !foundIndex {
Expand Down Expand Up @@ -304,22 +298,24 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
}
}

func (i *gatewayHandler) postHandler(w http.ResponseWriter, r *http.Request) {
nd, err := i.newDagFromReader(r.Body)
if err != nil {
internalWebError(w, err)
return
}
// TODO(cryptix): find these helpers somewhere else
func (i *gatewayHandler) newDagFromReader(r io.Reader) (*dag.Node, error) {
// TODO(cryptix): change and remove this helper once PR1136 is merged
// return ufs.AddFromReader(i.api.IpfsNode(), r.Body)
return importer.BuildDagFromReader(
i.api.IpfsNode().DAG,
chunk.DefaultSplitter(r))
}

k, err := i.api.IpfsNode().DAG.Add(nd)
func (i *gatewayHandler) postHandler(w http.ResponseWriter, r *http.Request) {
p, err := i.api.Add(r.Body)
if err != nil {
internalWebError(w, err)
return
}

i.addUserHeaders(w) // ok, _now_ write user's headers.
w.Header().Set("IPFS-Hash", k.String())
http.Redirect(w, r, ipfsPathPrefix+k.String(), http.StatusCreated)
w.Header().Set("X-IPFS-Path", p.String())
http.Redirect(w, r, ipfsPathPrefix+p.String(), http.StatusCreated)
}

func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
Expand Down
1 change: 1 addition & 0 deletions path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func (p Path) String() string {
}

// IsJustAKey returns true if the path is of the form <key> or /ipfs/<key>.
// TODO: this relies on using ParsePath() for instantiating
func (p Path) IsJustAKey() bool {
parts := p.Segments()
return (len(parts) == 2 && parts[0] == "ipfs")
Expand Down

0 comments on commit 35c8b67

Please sign in to comment.