151 строка
3.0 KiB
Go
151 строка
3.0 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package client implements a basic appfs client.
|
|
package client
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/mattermost/rsc/appfs/proto"
|
|
)
|
|
|
|
type Client struct {
|
|
Host string
|
|
User string
|
|
Password string
|
|
}
|
|
|
|
func (c *Client) url(op, path string) string {
|
|
scheme := "https"
|
|
if strings.HasPrefix(c.Host, "localhost:") {
|
|
scheme = "http"
|
|
}
|
|
if strings.HasSuffix(op, "/") && strings.HasPrefix(path, "/") {
|
|
path = path[1:]
|
|
}
|
|
return scheme + "://"+ c.User + ":" + c.Password + "@" + c.Host + op + path
|
|
}
|
|
|
|
func (c *Client) do(u string) error {
|
|
_, err := c.get(u)
|
|
return err
|
|
}
|
|
|
|
func (c *Client) get(u string) ([]byte, error) {
|
|
tries := 0
|
|
for {
|
|
r, err := http.Get(u)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer r.Body.Close()
|
|
data, err := ioutil.ReadAll(r.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if r.StatusCode != 200 {
|
|
if r.StatusCode == 500 {
|
|
if tries++; tries < 3 {
|
|
fmt.Printf("%s %s; sleeping\n", r.Status, data)
|
|
time.Sleep(5*time.Second)
|
|
continue
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("%s %s", r.Status, data)
|
|
}
|
|
return data, nil
|
|
}
|
|
panic("unreachable")
|
|
}
|
|
|
|
func (c *Client) post(u string, data []byte) ([]byte, error) {
|
|
tries := 0
|
|
for {
|
|
r, err := http.Post(u, proto.PostContentType, bytes.NewBuffer(data))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer r.Body.Close()
|
|
rdata, err := ioutil.ReadAll(r.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if r.StatusCode != 200 {
|
|
if r.StatusCode == 500 {
|
|
if tries++; tries < 3 {
|
|
fmt.Printf("%s %s; sleeping\n", r.Status, rdata)
|
|
time.Sleep(5*time.Second)
|
|
continue
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("%s %s", r.Status, rdata)
|
|
}
|
|
return rdata, nil
|
|
}
|
|
panic("unreachable")
|
|
}
|
|
|
|
func (c *Client) Create(path string, isdir bool) error {
|
|
u := c.url(proto.CreateURL, path)
|
|
if isdir {
|
|
u += "?dir=1"
|
|
}
|
|
return c.do(u)
|
|
}
|
|
|
|
func (c *Client) Read(path string) ([]byte, error) {
|
|
return c.get(c.url(proto.ReadURL, path))
|
|
}
|
|
|
|
func (c *Client) Write(path string, data []byte) error {
|
|
u := c.url(proto.WriteURL, path)
|
|
_, err := c.post(u, data)
|
|
return err
|
|
}
|
|
|
|
func (c *Client) Mkfs() error {
|
|
return c.do(c.url(proto.MkfsURL, ""))
|
|
}
|
|
|
|
func (c *Client) Stat(path string) (*proto.FileInfo, error) {
|
|
data, err := c.get(c.url(proto.StatURL, path))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var fi proto.FileInfo
|
|
if err := json.Unmarshal(data, &fi); err != nil {
|
|
return nil, err
|
|
}
|
|
return &fi, nil
|
|
}
|
|
|
|
func (c *Client) ReadDir(path string) ([]*proto.FileInfo, error) {
|
|
data, err := c.Read(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dec := json.NewDecoder(bytes.NewBuffer(data))
|
|
var out []*proto.FileInfo
|
|
for {
|
|
var fi proto.FileInfo
|
|
err := dec.Decode(&fi)
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
out = append(out, &fi)
|
|
}
|
|
return out, nil
|
|
}
|