116 lines
3.6 KiB
Go
116 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/h2non/bimg"
|
|
)
|
|
|
|
var (
|
|
ErrNotFound = NewError("Not found", http.StatusNotFound)
|
|
ErrInvalidAPIKey = NewError("Invalid or missing API key", http.StatusUnauthorized)
|
|
ErrMethodNotAllowed = NewError("HTTP method not allowed. Try with a POST or GET method (-enable-url-source flag must be defined)", http.StatusMethodNotAllowed)
|
|
ErrGetMethodNotAllowed = NewError("GET method not allowed. Make sure remote URL source is enabled by using the flag: -enable-url-source", http.StatusMethodNotAllowed)
|
|
ErrUnsupportedMedia = NewError("Unsupported media type", http.StatusNotAcceptable)
|
|
ErrOutputFormat = NewError("Unsupported output image format", http.StatusBadRequest)
|
|
ErrEmptyBody = NewError("Empty or unreadable image", http.StatusBadRequest)
|
|
ErrMissingParamFile = NewError("Missing required param: file", http.StatusBadRequest)
|
|
ErrInvalidFilePath = NewError("Invalid file path", http.StatusBadRequest)
|
|
ErrInvalidImageURL = NewError("Unvalid image URL", http.StatusBadRequest)
|
|
ErrMissingImageSource = NewError("Cannot process the image due to missing or invalid params", http.StatusBadRequest)
|
|
ErrNotImplemented = NewError("Not implemented endpoint", http.StatusNotImplemented)
|
|
ErrInvalidURLSignature = NewError("Invalid URL signature", http.StatusBadRequest)
|
|
ErrURLSignatureMismatch = NewError("URL signature mismatch", http.StatusForbidden)
|
|
)
|
|
|
|
type Error struct {
|
|
Message string `json:"message,omitempty"`
|
|
Code int `json:"status"`
|
|
}
|
|
|
|
func (e Error) JSON() []byte {
|
|
buf, _ := json.Marshal(e)
|
|
return buf
|
|
}
|
|
|
|
func (e Error) Error() string {
|
|
return e.Message
|
|
}
|
|
|
|
func (e Error) HTTPCode() int {
|
|
if e.Code >= 400 && e.Code <= 511 {
|
|
return e.Code
|
|
}
|
|
return http.StatusServiceUnavailable
|
|
}
|
|
|
|
func NewError(err string, code int) Error {
|
|
err = strings.Replace(err, "\n", "", -1)
|
|
return Error{Message: err, Code: code}
|
|
}
|
|
|
|
func sendErrorResponse(w http.ResponseWriter, httpStatusCode int, err error) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(httpStatusCode)
|
|
_, _ = w.Write([]byte(fmt.Sprintf("{\"error\":\"%s\", \"status\": %d}", err.Error(), httpStatusCode)))
|
|
}
|
|
|
|
func replyWithPlaceholder(req *http.Request, w http.ResponseWriter, errCaller Error, o ServerOptions) error {
|
|
var err error
|
|
bimgOptions := bimg.Options{
|
|
Force: true,
|
|
Crop: true,
|
|
Enlarge: true,
|
|
Type: ImageType(req.URL.Query().Get("type")),
|
|
}
|
|
|
|
bimgOptions.Width, err = parseInt(req.URL.Query().Get("width"))
|
|
if err != nil {
|
|
sendErrorResponse(w, http.StatusBadRequest, err)
|
|
return err
|
|
}
|
|
|
|
bimgOptions.Height, err = parseInt(req.URL.Query().Get("height"))
|
|
if err != nil {
|
|
sendErrorResponse(w, http.StatusBadRequest, err)
|
|
return err
|
|
}
|
|
|
|
// Resize placeholder to expected output
|
|
buf, err := bimg.Resize(o.PlaceholderImage, bimgOptions)
|
|
if err != nil {
|
|
sendErrorResponse(w, http.StatusBadRequest, err)
|
|
return err
|
|
}
|
|
|
|
// Use final response body image
|
|
image := buf
|
|
|
|
// Placeholder image response
|
|
w.Header().Set("Content-Type", GetImageMimeType(bimg.DetermineImageType(image)))
|
|
w.Header().Set("Error", string(errCaller.JSON()))
|
|
if o.PlaceholderStatus != 0 {
|
|
w.WriteHeader(o.PlaceholderStatus)
|
|
} else {
|
|
w.WriteHeader(errCaller.HTTPCode())
|
|
}
|
|
_, _ = w.Write(image)
|
|
|
|
return errCaller
|
|
}
|
|
|
|
func ErrorReply(req *http.Request, w http.ResponseWriter, err Error, o ServerOptions) {
|
|
// Reply with placeholder if required
|
|
if o.EnablePlaceholder || o.Placeholder != "" {
|
|
_ = replyWithPlaceholder(req, w, err, o)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(err.HTTPCode())
|
|
_, _ = w.Write(err.JSON())
|
|
}
|