-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
http.go
129 lines (111 loc) · 2.7 KB
/
http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
}