Merge branch 'json-rpc'

This commit is contained in:
Harshavardhana 2016-02-12 20:32:47 -08:00
commit 3fd637c1f4
9 changed files with 354 additions and 286 deletions

View File

@ -22,7 +22,7 @@ import (
router "github.com/gorilla/mux"
jsonrpc "github.com/gorilla/rpc/v2"
"github.com/gorilla/rpc/v2/json"
"github.com/gorilla/rpc/v2/json2"
"github.com/minio/minio-go"
"github.com/minio/minio/pkg/fs"
"github.com/minio/minio/pkg/probe"
@ -65,7 +65,7 @@ func getWebAPIHandler(web *WebAPI) http.Handler {
}
s := jsonrpc.NewServer()
codec := json.NewCodec()
codec := json2.NewCodec()
s.RegisterCodec(codec, "application/json")
s.RegisterCodec(codec, "application/json; charset=UTF-8")
s.RegisterService(web, "Web")

View File

@ -1,58 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2012 The Gorilla 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 gorilla/rpc/json provides a codec for JSON-RPC over HTTP services.
To register the codec in a RPC server:
import (
"http"
"github.com/gorilla/rpc/v2"
"github.com/gorilla/rpc/v2/json"
)
func init() {
s := rpc.NewServer()
s.RegisterCodec(json.NewCodec(), "application/json")
// [...]
http.Handle("/rpc", s)
}
A codec is tied to a content type. In the example above, the server will use
the JSON codec for requests with "application/json" as the value for the
"Content-Type" header.
This package follows the JSON-RPC 1.0 specification:
http://json-rpc.org/wiki/specification
Request format is:
method:
The name of the method to be invoked, as a string in dotted notation
as in "Service.Method".
params:
An array with a single object to pass as argument to the method.
id:
The request id, a uint. It is used to match the response with the
request that it is replying to.
Response format is:
result:
The Object that was returned by the invoked method,
or null in case there was an error invoking the method.
error:
An Error object if there was an error invoking the method,
or null if there was no error.
id:
The same id as the request it is responding to.
Check the gorilla/rpc documentation for more details:
http://gorilla-web.appspot.com/pkg/rpc
*/
package json

View File

@ -1,132 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2012 The Gorilla 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 json
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"reflect"
"testing"
"github.com/gorilla/rpc/v2"
)
var (
ErrResponseError = errors.New("response error")
ErrResponseJsonError = &Error{Data: map[string]interface{}{
"stackstrace": map[string]interface{}{"0": "foo()"},
"error": "a message",
}}
)
type Service1Request struct {
A int
B int
}
type Service1Response struct {
Result int
}
type Service1 struct {
}
func (t *Service1) Multiply(r *http.Request, req *Service1Request, res *Service1Response) error {
res.Result = req.A * req.B
return nil
}
func (t *Service1) ResponseError(r *http.Request, req *Service1Request, res *Service1Response) error {
return ErrResponseError
}
func (t *Service1) ResponseJsonError(r *http.Request, req *Service1Request, res *Service1Response) error {
return ErrResponseJsonError
}
func execute(t *testing.T, s *rpc.Server, method string, req, res interface{}) error {
if !s.HasMethod(method) {
t.Fatal("Expected to be registered:", method)
}
buf, _ := EncodeClientRequest(method, req)
body := bytes.NewBuffer(buf)
r, _ := http.NewRequest("POST", "http://localhost:8080/", body)
r.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
s.ServeHTTP(w, r)
return DecodeClientResponse(w.Body, res)
}
func executeRaw(t *testing.T, s *rpc.Server, req json.RawMessage) (int, *bytes.Buffer) {
r, _ := http.NewRequest("POST", "http://localhost:8080/", bytes.NewBuffer(req))
r.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
s.ServeHTTP(w, r)
return w.Code, w.Body
}
func field(name string, blob json.RawMessage) (v interface{}, ok bool) {
var obj map[string]interface{}
if err := json.Unmarshal(blob, &obj); err != nil {
return nil, false
}
v, ok = obj[name]
return
}
func TestService(t *testing.T) {
s := rpc.NewServer()
s.RegisterCodec(NewCodec(), "application/json")
s.RegisterService(new(Service1), "")
var res Service1Response
if err := execute(t, s, "Service1.Multiply", &Service1Request{4, 2}, &res); err != nil {
t.Error("Expected err to be nil, but got", err)
}
if res.Result != 8 {
t.Error("Expected res.Result to be 8, but got", res.Result)
}
if err := execute(t, s, "Service1.ResponseError", &Service1Request{4, 2}, &res); err == nil {
t.Errorf("Expected to get %q, but got nil", ErrResponseError)
} else if err.Error() != ErrResponseError.Error() {
t.Errorf("Expected to get %q, but got %q", ErrResponseError, err)
}
if code, res := executeRaw(t, s, json.RawMessage(`{"method":"Service1.Multiply","params":null,"id":5}`)); code != 400 {
t.Error("Expected response code to be 400, but got", code)
} else if v, ok := field("result", res.Bytes()); !ok || v != nil {
t.Errorf("Expected ok to be true and v to be nil, but got %v and %v", ok, v)
}
if err := execute(t, s, "Service1.ResponseJsonError", &Service1Request{4, 2}, &res); err == nil {
t.Errorf("Expected to get %q, but got nil", ErrResponseError)
} else if jsonErr, ok := err.(*Error); !ok {
t.Error("Expected err to be of a *json.Error type")
} else if !reflect.DeepEqual(jsonErr.Data, ErrResponseJsonError.Data) {
t.Errorf("Expected jsonErr to be %q, but got %q", ErrResponseJsonError, jsonErr)
}
}
func TestClientNullResult(t *testing.T) {
data := `{"jsonrpc": "2.0", "id": 8674665223082153551, "result": null}`
reader := bytes.NewReader([]byte(data))
var reply interface{}
err := DecodeClientResponse(reader, &reply)
if err == nil {
t.Fatal(err)
}
if err.Error() != "Unexpected null result" {
t.Fatalf("Unexpected error: %s", err)
}
}

View File

@ -1,13 +1,12 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2012-2013 The Gorilla Authors. All rights reserved.
// Copyright 2012 The Gorilla 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 json
package json2
import (
"encoding/json"
"fmt"
"io"
"math/rand"
)
@ -18,10 +17,15 @@ import (
// clientRequest represents a JSON-RPC request sent by a client.
type clientRequest struct {
// JSON-RPC protocol.
Version string `json:"jsonrpc"`
// A String containing the name of the method to be invoked.
Method string `json:"method"`
// Object to pass as request parameter to the method.
Params [1]interface{} `json:"params"`
Params interface{} `json:"params"`
// The request id. This can be of any type. It is used to match the
// response with the request that it is replying to.
Id uint64 `json:"id"`
@ -29,17 +33,18 @@ type clientRequest struct {
// clientResponse represents a JSON-RPC response returned to a client.
type clientResponse struct {
Result *json.RawMessage `json:"result"`
Error interface{} `json:"error"`
Id uint64 `json:"id"`
Version string `json:"jsonrpc"`
Result *json.RawMessage `json:"result"`
Error *json.RawMessage `json:"error"`
}
// EncodeClientRequest encodes parameters for a JSON-RPC client request.
func EncodeClientRequest(method string, args interface{}) ([]byte, error) {
c := &clientRequest{
Method: method,
Params: [1]interface{}{args},
Id: uint64(rand.Int63()),
Version: "2.0",
Method: method,
Params: args,
Id: uint64(rand.Int63()),
}
return json.Marshal(c)
}
@ -52,10 +57,19 @@ func DecodeClientResponse(r io.Reader, reply interface{}) error {
return err
}
if c.Error != nil {
return &Error{Data: c.Error}
jsonErr := &Error{}
if err := json.Unmarshal(*c.Error, jsonErr); err != nil {
return &Error{
Code: E_SERVER,
Message: string(*c.Error),
}
}
return jsonErr
}
if c.Result == nil {
return fmt.Errorf("Unexpected null result")
return ErrNullResult
}
return json.Unmarshal(*c.Result, reply)
}

39
vendor/github.com/gorilla/rpc/v2/json2/error.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2012 The Gorilla 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 json2
import (
"errors"
)
type ErrorCode int
const (
E_PARSE ErrorCode = -32700
E_INVALID_REQ ErrorCode = -32600
E_NO_METHOD ErrorCode = -32601
E_BAD_PARAMS ErrorCode = -32602
E_INTERNAL ErrorCode = -32603
E_SERVER ErrorCode = -32000
)
var ErrNullResult = errors.New("result is null")
type Error struct {
// A Number that indicates the error type that occurred.
Code ErrorCode `json:"code"` /* required */
// A String providing a short description of the error.
// The message SHOULD be limited to a concise single sentence.
Message string `json:"message"` /* required */
// A Primitive or Structured value that contains additional information about the error.
Data interface{} `json:"data"` /* optional */
}
func (e *Error) Error() string {
return e.Message
}

161
vendor/github.com/gorilla/rpc/v2/json2/json_test.go generated vendored Normal file
View File

@ -0,0 +1,161 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2012 The Gorilla 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 json2
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"testing"
"github.com/gorilla/rpc/v2"
)
// ResponseRecorder is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
type ResponseRecorder struct {
Code int // the HTTP response code from WriteHeader
HeaderMap http.Header // the HTTP response headers
Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
Flushed bool
}
// NewRecorder returns an initialized ResponseRecorder.
func NewRecorder() *ResponseRecorder {
return &ResponseRecorder{
HeaderMap: make(http.Header),
Body: new(bytes.Buffer),
}
}
// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
const DefaultRemoteAddr = "1.2.3.4"
// Header returns the response headers.
func (rw *ResponseRecorder) Header() http.Header {
return rw.HeaderMap
}
// Write always succeeds and writes to rw.Body, if not nil.
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
if rw.Body != nil {
rw.Body.Write(buf)
}
if rw.Code == 0 {
rw.Code = http.StatusOK
}
return len(buf), nil
}
// WriteHeader sets rw.Code.
func (rw *ResponseRecorder) WriteHeader(code int) {
rw.Code = code
}
// Flush sets rw.Flushed to true.
func (rw *ResponseRecorder) Flush() {
rw.Flushed = true
}
// ----------------------------------------------------------------------------
var ErrResponseError = errors.New("response error")
type Service1Request struct {
A int
B int
}
type Service1BadRequest struct {
V string `json:"jsonrpc"`
M string `json:"method"`
ID uint64 `json:"id"`
}
type Service1Response struct {
Result int
}
type Service1 struct {
}
func (t *Service1) Multiply(r *http.Request, req *Service1Request, res *Service1Response) error {
res.Result = req.A * req.B
return nil
}
func (t *Service1) ResponseError(r *http.Request, req *Service1Request, res *Service1Response) error {
return ErrResponseError
}
func execute(t *testing.T, s *rpc.Server, method string, req, res interface{}) error {
if !s.HasMethod(method) {
t.Fatal("Expected to be registered:", method)
}
buf, _ := EncodeClientRequest(method, req)
body := bytes.NewBuffer(buf)
r, _ := http.NewRequest("POST", "http://localhost:8080/", body)
r.Header.Set("Content-Type", "application/json")
w := NewRecorder()
s.ServeHTTP(w, r)
return DecodeClientResponse(w.Body, res)
}
func executeRaw(t *testing.T, s *rpc.Server, req interface{}, res interface{}) error {
j, _ := json.Marshal(req)
r, _ := http.NewRequest("POST", "http://localhost:8080/", bytes.NewBuffer(j))
r.Header.Set("Content-Type", "application/json")
w := NewRecorder()
s.ServeHTTP(w, r)
return DecodeClientResponse(w.Body, res)
}
func TestService(t *testing.T) {
s := rpc.NewServer()
s.RegisterCodec(NewCodec(), "application/json")
s.RegisterService(new(Service1), "")
var res Service1Response
if err := execute(t, s, "Service1.Multiply", &Service1Request{4, 2}, &res); err != nil {
t.Error("Expected err to be nil, but got:", err)
}
if res.Result != 8 {
t.Errorf("Wrong response: %v.", res.Result)
}
if err := execute(t, s, "Service1.ResponseError", &Service1Request{4, 2}, &res); err == nil {
t.Errorf("Expected to get %q, but got nil", ErrResponseError)
} else if err.Error() != ErrResponseError.Error() {
t.Errorf("Expected to get %q, but got %q", ErrResponseError, err)
}
if err := executeRaw(t, s, &Service1BadRequest{"2.0", "Service1.Multiply", 1}, &res); err == nil {
t.Errorf("Expected error but error in nil")
}
}
func TestDecodeNullResult(t *testing.T) {
data := `{"jsonrpc": "2.0", "id": 12345, "result": null}`
reader := bytes.NewReader([]byte(data))
var result interface{}
err := DecodeClientResponse(reader, &result)
if err != ErrNullResult {
t.Error("Expected err no be ErrNullResult, but got:", err)
}
if result != nil {
t.Error("Expected result to be nil, but got:", result)
}
}

View File

@ -3,29 +3,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package json
package json2
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"github.com/gorilla/rpc/v2"
)
var null = json.RawMessage([]byte("null"))
// An Error is a wrapper for a JSON interface value. It can be used by either
// a service's handler func to write more complex JSON data to an error field
// of a server's response, or by a client to read it.
type Error struct {
Data interface{}
}
func (e *Error) Error() string {
return fmt.Sprintf("%v", e.Data)
}
var Version = "2.0"
// ----------------------------------------------------------------------------
// Request and Response
@ -33,23 +21,36 @@ func (e *Error) Error() string {
// serverRequest represents a JSON-RPC request received by the server.
type serverRequest struct {
// JSON-RPC protocol.
Version string `json:"jsonrpc"`
// A String containing the name of the method to be invoked.
Method string `json:"method"`
// An Array of objects to pass as arguments to the method.
// A Structured value to pass as arguments to the method.
Params *json.RawMessage `json:"params"`
// The request id. This can be of any type. It is used to match the
// response with the request that it is replying to.
// The request id. MUST be a string, number or null.
// Our implementation will not do type checking for id.
// It will be copied as it is.
Id *json.RawMessage `json:"id"`
}
// serverResponse represents a JSON-RPC response returned by the server.
type serverResponse struct {
// JSON-RPC protocol.
Version string `json:"jsonrpc"`
// The Object that was returned by the invoked method. This must be null
// in case there was an error invoking the method.
Result interface{} `json:"result"`
// As per spec the member will be omitted if there was an error.
Result interface{} `json:"result,omitempty"`
// An Error object if there was an error invoking the method. It must be
// null if there was no error.
Error interface{} `json:"error"`
// As per spec the member will be omitted if there was no error.
Error *Error `json:"error,omitempty"`
// This must be the same id as the request it is responding to.
Id *json.RawMessage `json:"id"`
}
@ -58,18 +59,24 @@ type serverResponse struct {
// Codec
// ----------------------------------------------------------------------------
// NewcustomCodec returns a new JSON Codec based on passed encoder selector.
func NewCustomCodec(encSel rpc.EncoderSelector) *Codec {
return &Codec{encSel: encSel}
}
// NewCodec returns a new JSON Codec.
func NewCodec() *Codec {
return &Codec{}
return NewCustomCodec(rpc.DefaultEncoderSelector)
}
// Codec creates a CodecRequest to process each request.
type Codec struct {
encSel rpc.EncoderSelector
}
// NewRequest returns a CodecRequest.
func (c *Codec) NewRequest(r *http.Request) rpc.CodecRequest {
return newCodecRequest(r)
return newCodecRequest(r, c.encSel.Select(r))
}
// ----------------------------------------------------------------------------
@ -77,18 +84,33 @@ func (c *Codec) NewRequest(r *http.Request) rpc.CodecRequest {
// ----------------------------------------------------------------------------
// newCodecRequest returns a new CodecRequest.
func newCodecRequest(r *http.Request) rpc.CodecRequest {
func newCodecRequest(r *http.Request, encoder rpc.Encoder) rpc.CodecRequest {
// Decode the request body and check if RPC method is valid.
req := new(serverRequest)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
err = &Error{
Code: E_PARSE,
Message: err.Error(),
Data: req,
}
}
if req.Version != Version {
err = &Error{
Code: E_INVALID_REQ,
Message: "jsonrpc must be " + Version,
Data: req,
}
}
r.Body.Close()
return &CodecRequest{request: req, err: err}
return &CodecRequest{request: req, err: err, encoder: encoder}
}
// CodecRequest decodes and encodes a single request.
type CodecRequest struct {
request *serverRequest
err error
encoder rpc.Encoder
}
// Method returns the RPC method for the current request.
@ -101,16 +123,24 @@ func (c *CodecRequest) Method() (string, error) {
return "", c.err
}
// ReadRequest fills the request object for the RPC method.
// ReadRe<quest fills the request object for the RPC method.
func (c *CodecRequest) ReadRequest(args interface{}) error {
if c.err == nil {
if c.request.Params != nil {
// JSON params is array value. RPC params is struct.
// Unmarshal into array containing the request struct.
params := [1]interface{}{args}
c.err = json.Unmarshal(*c.request.Params, &params)
// JSON params structured object. Unmarshal to the args object.
err := json.Unmarshal(*c.request.Params, args)
if err != nil {
c.err = &Error{
Code: E_INVALID_REQ,
Message: err.Error(),
Data: c.request.Params,
}
}
} else {
c.err = errors.New("rpc: method request ill-formed: missing params field")
c.err = &Error{
Code: E_INVALID_REQ,
Message: "rpc: method request ill-formed: missing params field",
}
}
}
return c.err
@ -118,38 +148,43 @@ func (c *CodecRequest) ReadRequest(args interface{}) error {
// WriteResponse encodes the response and writes it to the ResponseWriter.
func (c *CodecRequest) WriteResponse(w http.ResponseWriter, reply interface{}) {
if c.request.Id != nil {
// Id is null for notifications and they don't have a response.
res := &serverResponse{
Result: reply,
Error: &null,
Id: c.request.Id,
}
c.writeServerResponse(w, 200, res)
}
}
func (c *CodecRequest) WriteError(w http.ResponseWriter, _ int, err error) {
res := &serverResponse{
Result: &null,
Id: c.request.Id,
Version: Version,
Result: reply,
Id: c.request.Id,
}
if jsonErr, ok := err.(*Error); ok {
res.Error = jsonErr.Data
} else {
res.Error = err.Error()
}
c.writeServerResponse(w, 400, res)
c.writeServerResponse(w, res)
}
func (c *CodecRequest) writeServerResponse(w http.ResponseWriter, status int, res *serverResponse) {
b, err := json.Marshal(res)
if err == nil {
w.WriteHeader(status)
func (c *CodecRequest) WriteError(w http.ResponseWriter, status int, err error) {
jsonErr, ok := err.(*Error)
if !ok {
jsonErr = &Error{
Code: E_SERVER,
Message: err.Error(),
}
}
res := &serverResponse{
Version: Version,
Error: jsonErr,
Id: c.request.Id,
}
c.writeServerResponse(w, res)
}
func (c *CodecRequest) writeServerResponse(w http.ResponseWriter, res *serverResponse) {
// Id is null for notifications and they don't have a response.
if c.request.Id != nil {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Write(b)
} else {
encoder := json.NewEncoder(c.encoder.Encode(w))
err := encoder.Encode(res)
// Not sure in which case will this happen. But seems harmless.
rpc.WriteError(w, 400, err.Error())
if err != nil {
rpc.WriteError(w, 400, err.Error())
}
}
}
type EmptyResponse struct {
}

6
vendor/vendor.json vendored
View File

@ -43,9 +43,9 @@
"revisionTime": "2015-11-05T07:45:51+08:00"
},
{
"path": "github.com/gorilla/rpc/v2/json",
"revision": "64e20900b8aa38bb0771dec71ba3bcc2b07fc8ec",
"revisionTime": "2015-11-05T07:45:51+08:00"
"path": "github.com/gorilla/rpc/v2/json2",
"revision": "839c4c31c6bb12c15f41802cf89325aa89439ac3",
"revisionTime": "2015-07-14T15:53:15-07:00"
},
{
"path": "github.com/mattn/go-isatty",

View File

@ -30,6 +30,7 @@ import (
jwtgo "github.com/dgrijalva/jwt-go"
"github.com/dustin/go-humanize"
"github.com/gorilla/rpc/v2/json2"
"github.com/minio/minio-go"
"github.com/minio/minio/pkg/disk"
"github.com/minio/minio/pkg/probe"
@ -60,7 +61,7 @@ func (web WebAPI) GetUIVersion(r *http.Request, args *GenericArgs, reply *Generi
// ServerInfo - get server info.
func (web *WebAPI) ServerInfo(r *http.Request, args *ServerInfoArgs, reply *ServerInfoRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
host, err := os.Hostname()
if err != nil {
@ -89,11 +90,11 @@ func (web *WebAPI) ServerInfo(r *http.Request, args *ServerInfoArgs, reply *Serv
// DiskInfo - get disk statistics.
func (web *WebAPI) DiskInfo(r *http.Request, args *DiskInfoArgs, reply *DiskInfoRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
info, e := disk.GetInfo(web.FSPath)
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
reply.DiskInfo = info
reply.UIVersion = uiVersion
@ -103,20 +104,24 @@ func (web *WebAPI) DiskInfo(r *http.Request, args *DiskInfoArgs, reply *DiskInfo
// MakeBucket - make a bucket.
func (web *WebAPI) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *GenericRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
reply.UIVersion = uiVersion
return web.Client.MakeBucket(args.BucketName, "", "")
e := web.Client.MakeBucket(args.BucketName, "", "")
if e != nil {
return &json2.Error{Message: e.Error()}
}
return nil
}
// ListBuckets - list buckets api.
func (web *WebAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *ListBucketsRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
buckets, e := web.Client.ListBuckets()
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
for _, bucket := range buckets {
reply.Buckets = append(reply.Buckets, BucketInfo{
@ -131,14 +136,14 @@ func (web *WebAPI) ListBuckets(r *http.Request, args *ListBucketsArgs, reply *Li
// ListObjects - list objects api.
func (web *WebAPI) ListObjects(r *http.Request, args *ListObjectsArgs, reply *ListObjectsRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
doneCh := make(chan struct{})
defer close(doneCh)
for object := range web.Client.ListObjects(args.BucketName, args.Prefix, false, doneCh) {
if object.Err != nil {
return object.Err
return &json2.Error{Message: object.Err.Error()}
}
objectInfo := ObjectInfo{
Key: object.Key,
@ -151,7 +156,7 @@ func (web *WebAPI) ListObjects(r *http.Request, args *ListObjectsArgs, reply *Li
if !strings.HasSuffix(object.Key, "/") && object.Size > 0 {
objectStatInfo, e := web.Client.StatObject(args.BucketName, object.Key)
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
objectInfo.ContentType = objectStatInfo.ContentType
}
@ -179,19 +184,19 @@ func getTargetHost(apiAddress, targetHost string) (string, *probe.Error) {
// PutObjectURL - generates url for upload access.
func (web *WebAPI) PutObjectURL(r *http.Request, args *PutObjectURLArgs, reply *PutObjectURLRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
targetHost, err := getTargetHost(web.apiAddress, args.TargetHost)
if err != nil {
return err.ToGoError()
return &json2.Error{Message: err.Cause.Error(), Data: err.String()}
}
client, e := minio.NewV4(targetHost, web.accessKeyID, web.secretAccessKey, web.inSecure)
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
signedURLStr, e := client.PresignedPutObject(args.BucketName, args.ObjectName, time.Duration(60*60)*time.Second)
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
reply.URL = signedURLStr
reply.UIVersion = uiVersion
@ -201,29 +206,29 @@ func (web *WebAPI) PutObjectURL(r *http.Request, args *PutObjectURLArgs, reply *
// GetObjectURL - generates url for download access.
func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *GetObjectURLRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
// See if object exists.
_, e := web.Client.StatObject(args.BucketName, args.ObjectName)
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
targetHost, err := getTargetHost(web.apiAddress, args.TargetHost)
if err != nil {
return err.ToGoError()
return &json2.Error{Message: err.Cause.Error(), Data: err.String()}
}
client, e := minio.NewV4(targetHost, web.accessKeyID, web.secretAccessKey, web.inSecure)
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
reqParams := make(url.Values)
// Set content disposition for browser to download the file.
reqParams.Set("response-content-disposition", fmt.Sprintf(`attachment; filename="%s"`, filepath.Base(args.ObjectName)))
signedURLStr, e := client.PresignedGetObject(args.BucketName, args.ObjectName, time.Duration(60*60)*time.Second, reqParams)
if e != nil {
return e
return &json2.Error{Message: e.Error()}
}
reply.URL = signedURLStr
reply.UIVersion = uiVersion
@ -233,10 +238,14 @@ func (web *WebAPI) GetObjectURL(r *http.Request, args *GetObjectURLArgs, reply *
// RemoveObject - removes an object.
func (web *WebAPI) RemoveObject(r *http.Request, args *RemoveObjectArgs, reply *GenericRep) error {
if !isAuthenticated(r) {
return errUnAuthorizedRequest
return &json2.Error{Message: "Unauthorized request"}
}
reply.UIVersion = uiVersion
return web.Client.RemoveObject(args.BucketName, args.ObjectName)
e := web.Client.RemoveObject(args.BucketName, args.ObjectName)
if e != nil {
return &json2.Error{Message: e.Error()}
}
return nil
}
// Login - user login handler.
@ -245,11 +254,11 @@ func (web *WebAPI) Login(r *http.Request, args *LoginArgs, reply *LoginRep) erro
if jwt.Authenticate(args.Username, args.Password) {
token, err := jwt.GenerateToken(args.Username)
if err != nil {
return err.ToGoError()
return &json2.Error{Message: err.Cause.Error(), Data: err.String()}
}
reply.Token = token
reply.UIVersion = uiVersion
return nil
}
return errInvalidCredentials
return &json2.Error{Message: "Invalid credentials"}
}