registry: use constants for http methods
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
d1817b6135
commit
441b031bda
|
@ -33,7 +33,7 @@ func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent st
|
||||||
return "", "", errdefs.System(errors.New("server Error: Server Address not set"))
|
return "", "", errdefs.System(errors.New("server Error: Server Address not set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", serverAddress+"users/", nil)
|
req, err := http.NewRequest(http.MethodGet, serverAddress+"users/", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent strin
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/"
|
endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/"
|
||||||
req, err := http.NewRequest("GET", endpointStr, nil)
|
req, err := http.NewRequest(http.MethodGet, endpointStr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !foundV2 {
|
if !foundV2 {
|
||||||
err = fallbackError{err: err}
|
err = fallbackError{err: err}
|
||||||
|
@ -262,7 +262,7 @@ func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.M
|
||||||
Timeout: 15 * time.Second,
|
Timeout: 15 * time.Second,
|
||||||
}
|
}
|
||||||
endpointStr := strings.TrimRight(endpoint.String(), "/") + "/v2/"
|
endpointStr := strings.TrimRight(endpoint.String(), "/") + "/v2/"
|
||||||
req, err := http.NewRequest("GET", endpointStr, nil)
|
req, err := http.NewRequest(http.MethodGet, endpointStr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ func (e *V1Endpoint) Ping() (PingResult, error) {
|
||||||
return PingResult{Standalone: false}, nil
|
return PingResult{Standalone: false}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", e.Path("_ping"), nil)
|
req, err := http.NewRequest(http.MethodGet, e.Path("_ping"), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PingResult{Standalone: false}, err
|
return PingResult{Standalone: false}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,19 +97,19 @@ func init() {
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
|
|
||||||
// /v1/
|
// /v1/
|
||||||
r.HandleFunc("/v1/_ping", handlerGetPing).Methods("GET")
|
r.HandleFunc("/v1/_ping", handlerGetPing).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/v1/images/{image_id:[^/]+}/{action:json|layer|ancestry}", handlerGetImage).Methods("GET")
|
r.HandleFunc("/v1/images/{image_id:[^/]+}/{action:json|layer|ancestry}", handlerGetImage).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/v1/images/{image_id:[^/]+}/{action:json|layer|checksum}", handlerPutImage).Methods("PUT")
|
r.HandleFunc("/v1/images/{image_id:[^/]+}/{action:json|layer|checksum}", handlerPutImage).Methods(http.MethodPut)
|
||||||
r.HandleFunc("/v1/repositories/{repository:.+}/tags", handlerGetDeleteTags).Methods("GET", "DELETE")
|
r.HandleFunc("/v1/repositories/{repository:.+}/tags", handlerGetDeleteTags).Methods(http.MethodGet, http.MethodDelete)
|
||||||
r.HandleFunc("/v1/repositories/{repository:.+}/tags/{tag:.+}", handlerGetTag).Methods("GET")
|
r.HandleFunc("/v1/repositories/{repository:.+}/tags/{tag:.+}", handlerGetTag).Methods(http.MethodGet)
|
||||||
r.HandleFunc("/v1/repositories/{repository:.+}/tags/{tag:.+}", handlerPutTag).Methods("PUT")
|
r.HandleFunc("/v1/repositories/{repository:.+}/tags/{tag:.+}", handlerPutTag).Methods(http.MethodPut)
|
||||||
r.HandleFunc("/v1/users{null:.*}", handlerUsers).Methods("GET", "POST", "PUT")
|
r.HandleFunc("/v1/users{null:.*}", handlerUsers).Methods(http.MethodGet, http.MethodPost, http.MethodPut)
|
||||||
r.HandleFunc("/v1/repositories/{repository:.+}{action:/images|/}", handlerImages).Methods("GET", "PUT", "DELETE")
|
r.HandleFunc("/v1/repositories/{repository:.+}{action:/images|/}", handlerImages).Methods(http.MethodGet, http.MethodPut, http.MethodDelete)
|
||||||
r.HandleFunc("/v1/repositories/{repository:.+}/auth", handlerAuth).Methods("PUT")
|
r.HandleFunc("/v1/repositories/{repository:.+}/auth", handlerAuth).Methods(http.MethodPut)
|
||||||
r.HandleFunc("/v1/search", handlerSearch).Methods("GET")
|
r.HandleFunc("/v1/search", handlerSearch).Methods(http.MethodGet)
|
||||||
|
|
||||||
// /v2/
|
// /v2/
|
||||||
r.HandleFunc("/v2/version", handlerGetPing).Methods("GET")
|
r.HandleFunc("/v2/version", handlerGetPing).Methods(http.MethodGet)
|
||||||
|
|
||||||
testHTTPServer = httptest.NewServer(handlerAccessLog(r))
|
testHTTPServer = httptest.NewServer(handlerAccessLog(r))
|
||||||
testHTTPSServer = httptest.NewTLSServer(handlerAccessLog(r))
|
testHTTPSServer = httptest.NewTLSServer(handlerAccessLog(r))
|
||||||
|
@ -350,7 +350,7 @@ func handlerGetDeleteTags(w http.ResponseWriter, r *http.Request) {
|
||||||
apiError(w, "Repository not found", 404)
|
apiError(w, "Repository not found", 404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method == "DELETE" {
|
if r.Method == http.MethodDelete {
|
||||||
delete(testRepositories, repositoryName.String())
|
delete(testRepositories, repositoryName.String())
|
||||||
writeResponse(w, true, 200)
|
writeResponse(w, true, 200)
|
||||||
return
|
return
|
||||||
|
@ -406,9 +406,9 @@ func handlerPutTag(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func handlerUsers(w http.ResponseWriter, r *http.Request) {
|
func handlerUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
code := 200
|
code := 200
|
||||||
if r.Method == "POST" {
|
if r.Method == http.MethodPost {
|
||||||
code = 201
|
code = 201
|
||||||
} else if r.Method == "PUT" {
|
} else if r.Method == http.MethodPut {
|
||||||
code = 204
|
code = 204
|
||||||
}
|
}
|
||||||
writeResponse(w, "", code)
|
writeResponse(w, "", code)
|
||||||
|
@ -418,7 +418,7 @@ func handlerImages(w http.ResponseWriter, r *http.Request) {
|
||||||
u, _ := url.Parse(testHTTPServer.URL)
|
u, _ := url.Parse(testHTTPServer.URL)
|
||||||
w.Header().Add("X-Docker-Endpoints", fmt.Sprintf("%s , %s ", u.Host, "test.example.com"))
|
w.Header().Add("X-Docker-Endpoints", fmt.Sprintf("%s , %s ", u.Host, "test.example.com"))
|
||||||
w.Header().Add("X-Docker-Token", fmt.Sprintf("FAKE-SESSION-%d", time.Now().UnixNano()))
|
w.Header().Add("X-Docker-Token", fmt.Sprintf("FAKE-SESSION-%d", time.Now().UnixNano()))
|
||||||
if r.Method == "PUT" {
|
if r.Method == http.MethodPut {
|
||||||
if strings.HasSuffix(r.URL.Path, "images") {
|
if strings.HasSuffix(r.URL.Path, "images") {
|
||||||
writeResponse(w, "", 204)
|
writeResponse(w, "", 204)
|
||||||
return
|
return
|
||||||
|
@ -426,7 +426,7 @@ func handlerImages(w http.ResponseWriter, r *http.Request) {
|
||||||
writeResponse(w, "", 200)
|
writeResponse(w, "", 200)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if r.Method == "DELETE" {
|
if r.Method == http.MethodDelete {
|
||||||
writeResponse(w, "", 204)
|
writeResponse(w, "", 204)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,12 +761,12 @@ func TestSearchRepositories(t *testing.T) {
|
||||||
|
|
||||||
func TestTrustedLocation(t *testing.T) {
|
func TestTrustedLocation(t *testing.T) {
|
||||||
for _, url := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} {
|
for _, url := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} {
|
||||||
req, _ := http.NewRequest("GET", url, nil)
|
req, _ := http.NewRequest(http.MethodGet, url, nil)
|
||||||
assert.Check(t, !trustedLocation(req))
|
assert.Check(t, !trustedLocation(req))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, url := range []string{"https://docker.io", "https://test.docker.com:80"} {
|
for _, url := range []string{"https://docker.io", "https://test.docker.com:80"} {
|
||||||
req, _ := http.NewRequest("GET", url, nil)
|
req, _ := http.NewRequest(http.MethodGet, url, nil)
|
||||||
assert.Check(t, trustedLocation(req))
|
assert.Check(t, trustedLocation(req))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -777,10 +777,10 @@ func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) {
|
||||||
{"https://foo.docker.io:7777", "http://bar.docker.com"},
|
{"https://foo.docker.io:7777", "http://bar.docker.com"},
|
||||||
{"https://foo.docker.io", "https://example.com"},
|
{"https://foo.docker.io", "https://example.com"},
|
||||||
} {
|
} {
|
||||||
reqFrom, _ := http.NewRequest("GET", urls[0], nil)
|
reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil)
|
||||||
reqFrom.Header.Add("Content-Type", "application/json")
|
reqFrom.Header.Add("Content-Type", "application/json")
|
||||||
reqFrom.Header.Add("Authorization", "super_secret")
|
reqFrom.Header.Add("Authorization", "super_secret")
|
||||||
reqTo, _ := http.NewRequest("GET", urls[1], nil)
|
reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil)
|
||||||
|
|
||||||
addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
|
addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
|
||||||
|
|
||||||
|
@ -801,10 +801,10 @@ func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) {
|
||||||
{"https://docker.io", "https://docker.com"},
|
{"https://docker.io", "https://docker.com"},
|
||||||
{"https://foo.docker.io:7777", "https://bar.docker.com"},
|
{"https://foo.docker.io:7777", "https://bar.docker.com"},
|
||||||
} {
|
} {
|
||||||
reqFrom, _ := http.NewRequest("GET", urls[0], nil)
|
reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil)
|
||||||
reqFrom.Header.Add("Content-Type", "application/json")
|
reqFrom.Header.Add("Content-Type", "application/json")
|
||||||
reqFrom.Header.Add("Authorization", "super_secret")
|
reqFrom.Header.Add("Authorization", "super_secret")
|
||||||
reqTo, _ := http.NewRequest("GET", urls[1], nil)
|
reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil)
|
||||||
|
|
||||||
addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
|
addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom})
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ func TestResumableRequestHeaderSimpleErrors(t *testing.T) {
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
req, err := http.NewRequest("GET", ts.URL, nil)
|
req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
resreq := &requestReader{}
|
resreq := &requestReader{}
|
||||||
|
@ -44,7 +44,7 @@ func TestResumableRequestHeaderNotTooMuchFailures(t *testing.T) {
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
||||||
var badReq *http.Request
|
var badReq *http.Request
|
||||||
badReq, err := http.NewRequest("GET", "I'm not an url", nil)
|
badReq, err := http.NewRequest(http.MethodGet, "I'm not an url", nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
resreq := &requestReader{
|
resreq := &requestReader{
|
||||||
|
@ -64,7 +64,7 @@ func TestResumableRequestHeaderTooMuchFailures(t *testing.T) {
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
||||||
var badReq *http.Request
|
var badReq *http.Request
|
||||||
badReq, err := http.NewRequest("GET", "I'm not an url", nil)
|
badReq, err := http.NewRequest(http.MethodGet, "I'm not an url", nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
resreq := &requestReader{
|
resreq := &requestReader{
|
||||||
|
@ -92,7 +92,7 @@ func (errorReaderCloser) Read(p []byte) (n int, err error) {
|
||||||
// If an unknown error is encountered, return 0, nil and log it
|
// If an unknown error is encountered, return 0, nil and log it
|
||||||
func TestResumableRequestReaderWithReadError(t *testing.T) {
|
func TestResumableRequestReaderWithReadError(t *testing.T) {
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
req, err := http.NewRequest("GET", "", nil)
|
req, err := http.NewRequest(http.MethodGet, "", nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
@ -123,7 +123,7 @@ func TestResumableRequestReaderWithReadError(t *testing.T) {
|
||||||
|
|
||||||
func TestResumableRequestReaderWithEOFWith416Response(t *testing.T) {
|
func TestResumableRequestReaderWithEOFWith416Response(t *testing.T) {
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
req, err := http.NewRequest("GET", "", nil)
|
req, err := http.NewRequest(http.MethodGet, "", nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
@ -159,7 +159,7 @@ func TestResumableRequestReaderWithServerDoesntSupportByteRanges(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
req, err := http.NewRequest("GET", ts.URL, nil)
|
req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
@ -185,7 +185,7 @@ func TestResumableRequestReaderWithZeroTotalSize(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
req, err := http.NewRequest("GET", ts.URL, nil)
|
req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
@ -210,7 +210,7 @@ func TestResumableRequestReader(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
req, err := http.NewRequest("GET", ts.URL, nil)
|
req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
@ -236,7 +236,7 @@ func TestResumableRequestReaderWithInitialResponse(t *testing.T) {
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
req, err := http.NewRequest("GET", ts.URL, nil)
|
req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
|
@ -289,7 +289,7 @@ func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io
|
||||||
imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID)
|
imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID)
|
||||||
)
|
)
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", imageURL, nil)
|
req, err := http.NewRequest(http.MethodGet, imageURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error while getting from the server: %v", err)
|
return nil, fmt.Errorf("Error while getting from the server: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -423,7 +423,7 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro
|
||||||
|
|
||||||
logrus.Debugf("[registry] Calling GET %s", repositoryTarget)
|
logrus.Debugf("[registry] Calling GET %s", repositoryTarget)
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", repositoryTarget, nil)
|
req, err := http.NewRequest(http.MethodGet, repositoryTarget, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -490,7 +490,7 @@ func (r *Session) PushImageChecksumRegistry(imgData *ImgData, registry string) e
|
||||||
|
|
||||||
logrus.Debugf("[registry] Calling PUT %s", u)
|
logrus.Debugf("[registry] Calling PUT %s", u)
|
||||||
|
|
||||||
req, err := http.NewRequest("PUT", u, nil)
|
req, err := http.NewRequest(http.MethodPut, u, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -528,7 +528,7 @@ func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regist
|
||||||
|
|
||||||
logrus.Debugf("[registry] Calling PUT %s", u)
|
logrus.Debugf("[registry] Calling PUT %s", u)
|
||||||
|
|
||||||
req, err := http.NewRequest("PUT", u, bytes.NewReader(jsonRaw))
|
req, err := http.NewRequest(http.MethodPut, u, bytes.NewReader(jsonRaw))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -573,7 +573,7 @@ func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry
|
||||||
h.Write([]byte{'\n'})
|
h.Write([]byte{'\n'})
|
||||||
checksumLayer := io.TeeReader(tarsumLayer, h)
|
checksumLayer := io.TeeReader(tarsumLayer, h)
|
||||||
|
|
||||||
req, err := http.NewRequest("PUT", u, checksumLayer)
|
req, err := http.NewRequest(http.MethodPut, u, checksumLayer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
@ -610,7 +610,7 @@ func (r *Session) PushRegistryTag(remote reference.Named, revision, tag, registr
|
||||||
revision = "\"" + revision + "\""
|
revision = "\"" + revision + "\""
|
||||||
path := fmt.Sprintf("repositories/%s/tags/%s", reference.Path(remote), tag)
|
path := fmt.Sprintf("repositories/%s/tags/%s", reference.Path(remote), tag)
|
||||||
|
|
||||||
req, err := http.NewRequest("PUT", registry+path, strings.NewReader(revision))
|
req, err := http.NewRequest(http.MethodPut, registry+path, strings.NewReader(revision))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -714,7 +714,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Session) putImageRequest(u string, headers map[string][]string, body []byte) (*http.Response, error) {
|
func (r *Session) putImageRequest(u string, headers map[string][]string, body []byte) (*http.Response, error) {
|
||||||
req, err := http.NewRequest("PUT", u, bytes.NewReader(body))
|
req, err := http.NewRequest(http.MethodPut, u, bytes.NewReader(body))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -741,7 +741,7 @@ func (r *Session) SearchRepositories(term string, limit int) (*registrytypes.Sea
|
||||||
logrus.Debugf("Index server: %s", r.indexEndpoint)
|
logrus.Debugf("Index server: %s", r.indexEndpoint)
|
||||||
u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit))
|
u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit))
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u, nil)
|
req, err := http.NewRequest(http.MethodGet, u, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(errdefs.InvalidParameter(err), "Error building request")
|
return nil, errors.Wrap(errdefs.InvalidParameter(err), "Error building request")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue