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
 | 
						|
 | 
						|
}
 |