83 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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
 | |
| 
 | |
| }
 |