docserver.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package docserver
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "net/http"
  6. "github.com/ethereum/go-ethereum/common"
  7. "github.com/ethereum/go-ethereum/crypto"
  8. )
  9. // http://golang.org/pkg/net/http/#RoundTripper
  10. var (
  11. schemes = map[string]func(*DocServer) http.RoundTripper{
  12. // Simple File server from local disk file:///etc/passwd :)
  13. "file": fileServerOnDocRoot,
  14. }
  15. )
  16. func fileServerOnDocRoot(ds *DocServer) http.RoundTripper {
  17. return http.NewFileTransport(http.Dir(ds.DocRoot))
  18. }
  19. type DocServer struct {
  20. *http.Transport
  21. DocRoot string
  22. }
  23. func New(docRoot string) (self *DocServer, err error) {
  24. self = &DocServer{
  25. Transport: &http.Transport{},
  26. DocRoot: docRoot,
  27. }
  28. err = self.RegisterProtocols(schemes)
  29. return
  30. }
  31. // Clients should be reused instead of created as needed. Clients are safe for concurrent use by multiple goroutines.
  32. // A Client is higher-level than a RoundTripper (such as Transport) and additionally handles HTTP details such as cookies and redirects.
  33. func (self *DocServer) Client() *http.Client {
  34. return &http.Client{
  35. Transport: self,
  36. }
  37. }
  38. func (self *DocServer) RegisterProtocols(schemes map[string]func(*DocServer) http.RoundTripper) (err error) {
  39. for scheme, rtf := range schemes {
  40. self.RegisterProtocol(scheme, rtf(self))
  41. }
  42. return
  43. }
  44. func (self *DocServer) GetAuthContent(uri string, hash common.Hash) (content []byte, err error) {
  45. // retrieve content
  46. resp, err := self.Client().Get(uri)
  47. defer resp.Body.Close()
  48. if err != nil {
  49. return
  50. }
  51. content, err = ioutil.ReadAll(resp.Body)
  52. if err != nil {
  53. return
  54. }
  55. // check hash to authenticate content
  56. hashbytes := crypto.Sha3(content)
  57. var chash common.Hash
  58. copy(chash[:], hashbytes)
  59. if chash != hash {
  60. content = nil
  61. err = fmt.Errorf("content hash mismatch")
  62. }
  63. return
  64. }