mirror of https://github.com/portainer/portainer
110 lines
2.8 KiB
Go
110 lines
2.8 KiB
Go
package proxy
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/portainer/portainer"
|
|
)
|
|
|
|
const (
|
|
// ErrEmptyResponseBody defines an error raised when portainer excepts to parse the body of a HTTP response and there is nothing to parse
|
|
ErrEmptyResponseBody = portainer.Error("Empty response body")
|
|
// ErrInvalidResponseContent defines an error raised when Portainer excepts a JSON array and get something else.
|
|
ErrInvalidResponseContent = portainer.Error("Invalid Docker response")
|
|
)
|
|
|
|
func extractJSONField(jsonObject map[string]interface{}, key string) map[string]interface{} {
|
|
object := jsonObject[key]
|
|
if object != nil {
|
|
return object.(map[string]interface{})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getResponseAsJSONOBject(response *http.Response) (map[string]interface{}, error) {
|
|
responseData, err := getResponseBodyAsGenericJSON(response)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responseObject := responseData.(map[string]interface{})
|
|
return responseObject, nil
|
|
}
|
|
|
|
func getResponseAsJSONArray(response *http.Response) ([]interface{}, error) {
|
|
responseData, err := getResponseBodyAsGenericJSON(response)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch responseObject := responseData.(type) {
|
|
case []interface{}:
|
|
return responseObject, nil
|
|
case map[string]interface{}:
|
|
if responseObject["message"] != nil {
|
|
return nil, portainer.Error(responseObject["message"].(string))
|
|
}
|
|
log.Printf("Response: %+v\n", responseObject)
|
|
return nil, ErrInvalidResponseContent
|
|
default:
|
|
log.Printf("Response: %+v\n", responseObject)
|
|
return nil, ErrInvalidResponseContent
|
|
}
|
|
}
|
|
|
|
func getResponseBodyAsGenericJSON(response *http.Response) (interface{}, error) {
|
|
var data interface{}
|
|
if response.Body != nil {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = response.Body.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = json.Unmarshal(body, &data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return data, nil
|
|
}
|
|
return nil, ErrEmptyResponseBody
|
|
}
|
|
|
|
func writeAccessDeniedResponse() (*http.Response, error) {
|
|
response := &http.Response{}
|
|
err := rewriteResponse(response, portainer.ErrResourceAccessDenied, http.StatusForbidden)
|
|
return response, err
|
|
}
|
|
|
|
func rewriteAccessDeniedResponse(response *http.Response) error {
|
|
return rewriteResponse(response, portainer.ErrResourceAccessDenied, http.StatusForbidden)
|
|
}
|
|
|
|
func rewriteResponse(response *http.Response, newResponseData interface{}, statusCode int) error {
|
|
jsonData, err := json.Marshal(newResponseData)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
body := ioutil.NopCloser(bytes.NewReader(jsonData))
|
|
response.StatusCode = statusCode
|
|
response.Body = body
|
|
response.ContentLength = int64(len(jsonData))
|
|
|
|
if response.Header == nil {
|
|
response.Header = make(http.Header)
|
|
}
|
|
response.Header.Set("Content-Length", strconv.Itoa(len(jsonData)))
|
|
|
|
return nil
|
|
}
|