http.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package repository
  2. import (
  3. "errors"
  4. "net/http"
  5. "fyne.io/fyne/v2"
  6. "fyne.io/fyne/v2/storage/repository"
  7. )
  8. // declare conformance with repository types
  9. var _ repository.Repository = (*HTTPRepository)(nil)
  10. type remoteFile struct {
  11. *http.Response
  12. uri fyne.URI
  13. }
  14. func (f *remoteFile) Close() error {
  15. if f.Response == nil {
  16. return nil
  17. }
  18. return f.Response.Body.Close()
  19. }
  20. func (f *remoteFile) Read(p []byte) (int, error) {
  21. if f.Response == nil {
  22. return 0, nil
  23. }
  24. return f.Response.Body.Read(p)
  25. }
  26. func (f *remoteFile) URI() fyne.URI {
  27. return f.uri
  28. }
  29. // HTTPRepository implements a proxy for interacting with remote resources
  30. // using golang's net/http library.
  31. //
  32. // This repository is suitable to handle the http:// and https:// scheme.
  33. //
  34. // Since: 2.1
  35. type HTTPRepository struct{}
  36. // NewHTTPRepository creates a new HTTPRepository instance.
  37. // The caller needs to call repository.Register() with the result of this function.
  38. //
  39. // Since: 2.1
  40. func NewHTTPRepository() *HTTPRepository {
  41. return &HTTPRepository{}
  42. }
  43. func constructURI(u fyne.URI) string {
  44. uri := ""
  45. uri += u.Scheme() + "://"
  46. uri += u.Authority()
  47. if u.Path() != "" {
  48. uri += u.Path()
  49. }
  50. if u.Query() != "" {
  51. uri += "?" + u.Query()
  52. }
  53. if u.Fragment() != "" {
  54. uri += "#" + u.Fragment()
  55. }
  56. return uri
  57. }
  58. // Exists checks whether the the resource at u returns a
  59. // non "404 NOT FOUND" response header.
  60. //
  61. // Implements: repository.Repository
  62. //
  63. // Since: 2.1
  64. func (r *HTTPRepository) Exists(u fyne.URI) (bool, error) {
  65. uri := constructURI(u)
  66. resp, err := http.Head(uri)
  67. if err != nil {
  68. return false, err
  69. }
  70. if resp.StatusCode == http.StatusNotFound {
  71. return false, nil
  72. }
  73. return true, nil
  74. }
  75. // Reader provides a interface for reading the body of the response received
  76. // from the request to u.
  77. //
  78. // Implements: repository.Repository
  79. //
  80. // Since: 2.1
  81. func (r *HTTPRepository) Reader(u fyne.URI) (fyne.URIReadCloser, error) {
  82. uri := constructURI(u)
  83. resp, err := http.Get(uri)
  84. return &remoteFile{Response: resp, uri: u}, err
  85. }
  86. // CanRead makes a HEAD HTTP request to analyse the headers received
  87. // from the remote server.
  88. // Any response status code apart from 2xx is considered to be invalid.
  89. //
  90. // Implements: repository.Repository
  91. //
  92. // Since: 2.1
  93. func (r *HTTPRepository) CanRead(u fyne.URI) (bool, error) {
  94. uri := constructURI(u)
  95. resp, err := http.Head(uri)
  96. if err != nil {
  97. return false, err
  98. }
  99. if resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusIMUsed {
  100. return false, errors.New("remote server did not return a successful response")
  101. }
  102. return true, nil
  103. }
  104. // Destroy satisfies the repository.Repository interface.
  105. //
  106. // Implements: repository.Repository
  107. //
  108. // Since: 2.1
  109. func (r *HTTPRepository) Destroy(string) {
  110. // do nothing
  111. }