diff options
Diffstat (limited to 'common/docserver/docserver.go')
-rw-r--r-- | common/docserver/docserver.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/common/docserver/docserver.go b/common/docserver/docserver.go new file mode 100644 index 000000000..5e076aa7e --- /dev/null +++ b/common/docserver/docserver.go @@ -0,0 +1,82 @@ +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, + } +) + +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 func() { + if resp != nil { + 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 + +} |