130 lines
2.7 KiB
Go
130 lines
2.7 KiB
Go
|
package repository
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"net/http"
|
||
|
|
||
|
"fyne.io/fyne/v2"
|
||
|
"fyne.io/fyne/v2/storage/repository"
|
||
|
)
|
||
|
|
||
|
// declare conformance with repository types
|
||
|
var _ repository.Repository = (*HTTPRepository)(nil)
|
||
|
|
||
|
type remoteFile struct {
|
||
|
*http.Response
|
||
|
uri fyne.URI
|
||
|
}
|
||
|
|
||
|
func (f *remoteFile) Close() error {
|
||
|
if f.Response == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return f.Response.Body.Close()
|
||
|
}
|
||
|
|
||
|
func (f *remoteFile) Read(p []byte) (int, error) {
|
||
|
if f.Response == nil {
|
||
|
return 0, nil
|
||
|
}
|
||
|
return f.Response.Body.Read(p)
|
||
|
}
|
||
|
|
||
|
func (f *remoteFile) URI() fyne.URI {
|
||
|
return f.uri
|
||
|
}
|
||
|
|
||
|
// HTTPRepository implements a proxy for interacting with remote resources
|
||
|
// using golang's net/http library.
|
||
|
//
|
||
|
// This repository is suitable to handle the http:// and https:// scheme.
|
||
|
//
|
||
|
// Since: 2.1
|
||
|
type HTTPRepository struct{}
|
||
|
|
||
|
// NewHTTPRepository creates a new HTTPRepository instance.
|
||
|
// The caller needs to call repository.Register() with the result of this function.
|
||
|
//
|
||
|
// Since: 2.1
|
||
|
func NewHTTPRepository() *HTTPRepository {
|
||
|
return &HTTPRepository{}
|
||
|
}
|
||
|
|
||
|
func constructURI(u fyne.URI) string {
|
||
|
uri := ""
|
||
|
uri += u.Scheme() + "://"
|
||
|
uri += u.Authority()
|
||
|
if u.Path() != "" {
|
||
|
uri += u.Path()
|
||
|
}
|
||
|
if u.Query() != "" {
|
||
|
uri += "?" + u.Query()
|
||
|
}
|
||
|
if u.Fragment() != "" {
|
||
|
uri += "#" + u.Fragment()
|
||
|
}
|
||
|
|
||
|
return uri
|
||
|
}
|
||
|
|
||
|
// Exists checks whether the the resource at u returns a
|
||
|
// non "404 NOT FOUND" response header.
|
||
|
//
|
||
|
// Implements: repository.Repository
|
||
|
//
|
||
|
// Since: 2.1
|
||
|
func (r *HTTPRepository) Exists(u fyne.URI) (bool, error) {
|
||
|
uri := constructURI(u)
|
||
|
resp, err := http.Head(uri)
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
if resp.StatusCode == http.StatusNotFound {
|
||
|
return false, nil
|
||
|
}
|
||
|
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
// Reader provides a interface for reading the body of the response received
|
||
|
// from the request to u.
|
||
|
//
|
||
|
// Implements: repository.Repository
|
||
|
//
|
||
|
// Since: 2.1
|
||
|
func (r *HTTPRepository) Reader(u fyne.URI) (fyne.URIReadCloser, error) {
|
||
|
uri := constructURI(u)
|
||
|
resp, err := http.Get(uri)
|
||
|
|
||
|
return &remoteFile{Response: resp, uri: u}, err
|
||
|
}
|
||
|
|
||
|
// CanRead makes a HEAD HTTP request to analyse the headers received
|
||
|
// from the remote server.
|
||
|
// Any response status code apart from 2xx is considered to be invalid.
|
||
|
//
|
||
|
// Implements: repository.Repository
|
||
|
//
|
||
|
// Since: 2.1
|
||
|
func (r *HTTPRepository) CanRead(u fyne.URI) (bool, error) {
|
||
|
uri := constructURI(u)
|
||
|
resp, err := http.Head(uri)
|
||
|
if err != nil {
|
||
|
return false, err
|
||
|
}
|
||
|
if resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusIMUsed {
|
||
|
return false, errors.New("remote server did not return a successful response")
|
||
|
}
|
||
|
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
// Destroy satisfies the repository.Repository interface.
|
||
|
//
|
||
|
// Implements: repository.Repository
|
||
|
//
|
||
|
// Since: 2.1
|
||
|
func (r *HTTPRepository) Destroy(string) {
|
||
|
// do nothing
|
||
|
}
|