aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/docserver/docserver.go93
-rw-r--r--common/docserver/docserver_test.go38
2 files changed, 131 insertions, 0 deletions
diff --git a/common/docserver/docserver.go b/common/docserver/docserver.go
new file mode 100644
index 000000000..5d37ac97c
--- /dev/null
+++ b/common/docserver/docserver.go
@@ -0,0 +1,93 @@
+package docserver
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+// http://golang.org/pkg/net/http/#RoundTripper
+var (
+ schemes = map[string]func(*DocServer) http.RoundTripper{
+ // Simple File server from local disk file:///etc/passwd :)
+ "file": fileServerOnDocRoot,
+
+ // Swarm RoundTripper for bzz scheme bzz://mydomain/contact/twitter.json
+ // "bzz": &bzz.FileServer{},
+
+ // swarm remote file system call bzzfs:///etc/passwd
+ // "bzzfs": &bzzfs.FileServer{},
+
+ // restful peer protocol RoundTripper for enode scheme:
+ // POST suggestPeer DELETE removePeer PUT switch protocols
+ // RPC - standard protocol provides arc API for self enode (very safe remote server only connects to registered enode)
+ // POST enode://ae234dfgc56b..@128.56.68.5:3456/eth/getBlock/356eac67890fe
+ // and remote peer protocol
+ // POST enode://ae234dfgc56b..@128.56.68.5:3456/eth/getBlock/356eac67890fe
+ // proxy protoocol
+
+ }
+)
+
+func fileServerOnDocRoot(ds *DocServer) http.RoundTripper {
+ return http.NewFileTransport(http.Dir(ds.DocRoot))
+}
+
+type DocServer struct {
+ *http.Transport
+ DocRoot string
+}
+
+func New(docRoot string) (self *DocServer, err error) {
+ self = &DocServer{
+ Transport: &http.Transport{},
+ DocRoot: docRoot,
+ }
+ err = self.RegisterProtocols(schemes)
+ return
+}
+
+// Clients should be reused instead of created as needed. Clients are safe for concurrent use by multiple goroutines.
+
+// A Client is higher-level than a RoundTripper (such as Transport) and additionally handles HTTP details such as cookies and redirects.
+
+func (self *DocServer) Client() *http.Client {
+ return &http.Client{
+ Transport: self,
+ }
+}
+
+func (self *DocServer) RegisterProtocols(schemes map[string]func(*DocServer) http.RoundTripper) (err error) {
+ for scheme, rtf := range schemes {
+ self.RegisterProtocol(scheme, rtf(self))
+ }
+ return
+}
+
+func (self *DocServer) GetAuthContent(uri string, hash common.Hash) (content []byte, err error) {
+ // retrieve content
+ resp, err := self.Client().Get(uri)
+ defer resp.Body.Close()
+ if err != nil {
+ return
+ }
+ content, err = ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return
+ }
+
+ // check hash to authenticate content
+ hashbytes := crypto.Sha3(content)
+ var chash common.Hash
+ copy(chash[:], hashbytes)
+ if chash != hash {
+ content = nil
+ err = fmt.Errorf("content hash mismatch")
+ }
+
+ return
+
+}
diff --git a/common/docserver/docserver_test.go b/common/docserver/docserver_test.go
new file mode 100644
index 000000000..400d7447a
--- /dev/null
+++ b/common/docserver/docserver_test.go
@@ -0,0 +1,38 @@
+package docserver
+
+import (
+ "io/ioutil"
+ "os"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+func TestGetAuthContent(t *testing.T) {
+ text := "test"
+ hash := common.Hash{}
+ copy(hash[:], crypto.Sha3([]byte(text)))
+ ioutil.WriteFile("/tmp/test.content", []byte(text), os.ModePerm)
+
+ ds, err := New("/tmp/")
+ content, err := ds.GetAuthContent("file:///test.content", hash)
+ if err != nil {
+ t.Errorf("no error expected, got %v", err)
+ }
+ if string(content) != text {
+ t.Errorf("incorrect content. expected %v, got %v", text, string(content))
+ }
+
+ hash = common.Hash{}
+ content, err = ds.GetAuthContent("file:///test.content", hash)
+ expected := "content hash mismatch"
+ if err == nil {
+ t.Errorf("expected error, got nothing")
+ } else {
+ if err.Error() != expected {
+ t.Errorf("expected error '%s' got '%v'", expected, err)
+ }
+ }
+
+}