Bläddra i källkod

Advanced url format

DarthSim 7 år sedan
förälder
incheckning
5dcad5430a
3 ändrade filer med 288 tillägg och 78 borttagningar
  1. 0 15
      process.go
  2. 288 0
      processing_options.go
  3. 0 63
      server.go

+ 0 - 15
process.go

@@ -62,21 +62,6 @@ const (
 	CROP
 )
 
-var resizeTypes = map[string]resizeType{
-	"fit":  FIT,
-	"fill": FILL,
-	"crop": CROP,
-}
-
-type processingOptions struct {
-	Resize  resizeType
-	Width   int
-	Height  int
-	Gravity gravityType
-	Enlarge bool
-	Format  imageType
-}
-
 var vipsSupportSmartcrop bool
 var vipsTypeSupportLoad = make(map[imageType]bool)
 var vipsTypeSupportSave = make(map[imageType]bool)

+ 288 - 0
processing_options.go

@@ -0,0 +1,288 @@
+package main
+
+import (
+	"C"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+var resizeTypes = map[string]resizeType{
+	"fit":  FIT,
+	"fill": FILL,
+	"crop": CROP,
+}
+
+type processingOptions struct {
+	Resize  resizeType
+	Width   int
+	Height  int
+	Gravity gravityType
+	Enlarge bool
+	Format  imageType
+}
+
+func defaultProcessingOptions() processingOptions {
+	return processingOptions{
+		Resize:  FIT,
+		Width:   0,
+		Height:  0,
+		Gravity: CENTER,
+		Enlarge: false,
+		Format:  JPEG,
+	}
+}
+
+func decodeUrl(parts []string) (string, imageType, error) {
+	var imgType imageType = JPEG
+
+	urlParts := strings.Split(strings.Join(parts, ""), ".")
+
+	if len(urlParts) > 2 {
+		return "", 0, errors.New("Invalid url encoding")
+	}
+
+	if len(urlParts) == 2 {
+		if f, ok := imageTypes[urlParts[1]]; ok {
+			imgType = f
+		} else {
+			return "", 0, fmt.Errorf("Invalid image format: %s", urlParts[1])
+		}
+	}
+
+	url, err := base64.RawURLEncoding.DecodeString(urlParts[0])
+	if err != nil {
+		return "", 0, errors.New("Invalid url encoding")
+	}
+
+	return string(url), imgType, nil
+}
+
+func applyWidthOption(po *processingOptions, args []string) error {
+	if len(args) > 1 {
+		return fmt.Errorf("Invalid width arguments: %v", args)
+	}
+
+	if w, err := strconv.Atoi(args[0]); err == nil || w >= 0 {
+		po.Width = w
+	} else {
+		return fmt.Errorf("Invalid width: %s", args[0])
+	}
+
+	return nil
+}
+
+func applyHeightOption(po *processingOptions, args []string) error {
+	if len(args) > 1 {
+		return fmt.Errorf("Invalid height arguments: %v", args)
+	}
+
+	if h, err := strconv.Atoi(args[0]); err == nil || po.Height >= 0 {
+		po.Height = h
+	} else {
+		return fmt.Errorf("Invalid height: %s", args[0])
+	}
+
+	return nil
+}
+
+func applyEnlargeOption(po *processingOptions, args []string) error {
+	if len(args) > 1 {
+		return fmt.Errorf("Invalid enlarge arguments: %v", args)
+	}
+
+	po.Enlarge = args[0] != "0"
+
+	return nil
+}
+
+func applySizeOption(po *processingOptions, args []string) (err error) {
+	if len(args) > 3 {
+		return fmt.Errorf("Invalid size arguments: %v", args)
+	}
+
+	if len(args) >= 1 {
+		if err = applyWidthOption(po, args[0:1]); err != nil {
+			return
+		}
+	}
+
+	if len(args) >= 2 {
+		if err = applyHeightOption(po, args[1:2]); err != nil {
+			return
+		}
+	}
+
+	if len(args) == 3 {
+		if err = applyEnlargeOption(po, args[2:3]); err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func applyResizeOption(po *processingOptions, args []string) error {
+	if len(args) > 4 {
+		return fmt.Errorf("Invalid resize arguments: %v", args)
+	}
+
+	if r, ok := resizeTypes[args[0]]; ok {
+		po.Resize = r
+	} else {
+		return fmt.Errorf("Invalid resize type: %s", args[0])
+	}
+
+	if len(args) > 1 {
+		if err := applySizeOption(po, args[1:]); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func applyGravityOption(po *processingOptions, args []string) error {
+	if len(args) > 1 {
+		return fmt.Errorf("Invalid resize arguments: %v", args)
+	}
+
+	if g, ok := gravityTypes[args[0]]; ok {
+		po.Gravity = g
+	} else {
+		return fmt.Errorf("Invalid gravity: %s", args[0])
+	}
+
+	return nil
+}
+
+func applyFormatOption(po *processingOptions, imgType imageType) error {
+	if !vipsTypeSupportSave[imgType] {
+		return errors.New("Resulting image type not supported")
+	}
+
+	po.Format = imgType
+
+	return nil
+}
+
+func applyProcessingOption(po *processingOptions, name string, args []string) error {
+	switch name {
+	case "resize":
+		if err := applyResizeOption(po, args); err != nil {
+			return err
+		}
+	case "size":
+		if err := applySizeOption(po, args); err != nil {
+			return err
+		}
+	case "width":
+		if err := applyWidthOption(po, args); err != nil {
+			return err
+		}
+	case "height":
+		if err := applyHeightOption(po, args); err != nil {
+			return err
+		}
+	case "enlarge":
+		if err := applyEnlargeOption(po, args); err != nil {
+			return err
+		}
+	case "gravity":
+		if err := applyGravityOption(po, args); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func parsePathAdvanced(parts []string) (string, processingOptions, error) {
+	var urlStart int
+
+	po := defaultProcessingOptions()
+
+	for i, part := range parts {
+		args := strings.Split(part, ":")
+
+		if len(args) == 1 {
+			urlStart = i
+			break
+		}
+
+		if err := applyProcessingOption(&po, args[0], args[1:]); err != nil {
+			return "", po, err
+		}
+	}
+
+	url, imgType, err := decodeUrl(parts[urlStart:])
+	if err != nil {
+		return "", po, err
+	}
+
+	if err := applyFormatOption(&po, imgType); err != nil {
+		return "", po, errors.New("Resulting image type not supported")
+	}
+
+	return string(url), po, nil
+}
+
+func parsePathSimple(parts []string) (string, processingOptions, error) {
+	var po processingOptions
+	var err error
+
+	if len(parts) < 6 {
+		return "", po, errors.New("Invalid path")
+	}
+
+	po.Resize = resizeTypes[parts[0]]
+
+	if err = applyWidthOption(&po, parts[1:2]); err != nil {
+		return "", po, err
+	}
+
+	if err = applyHeightOption(&po, parts[2:3]); err != nil {
+		return "", po, err
+	}
+
+	if err = applyGravityOption(&po, parts[3:4]); err != nil {
+		return "", po, err
+	}
+
+	if err = applyEnlargeOption(&po, parts[4:5]); err != nil {
+		return "", po, err
+	}
+
+	url, imgType, err := decodeUrl(parts[5:])
+	if err != nil {
+		return "", po, err
+	}
+
+	if err := applyFormatOption(&po, imgType); err != nil {
+		return "", po, errors.New("Resulting image type not supported")
+	}
+
+	return string(url), po, nil
+}
+
+func parsePath(r *http.Request) (string, processingOptions, error) {
+	path := r.URL.Path
+	parts := strings.Split(strings.TrimPrefix(path, "/"), "/")
+
+	if len(parts) < 3 {
+		return "", processingOptions{}, errors.New("Invalid path")
+	}
+
+	// if err := validatePath(parts[0], strings.TrimPrefix(path, fmt.Sprintf("/%s", parts[0]))); err != nil {
+	// 	return "", processingOptions{}, err
+	// }
+
+	if _, ok := resizeTypes[parts[1]]; ok {
+		return parsePathSimple(parts[1:])
+	} else {
+		return parsePathAdvanced(parts[1:])
+	}
+}

+ 0 - 63
server.go

@@ -5,8 +5,6 @@ import (
 	"compress/gzip"
 	"context"
 	"crypto/subtle"
-	"encoding/base64"
-	"errors"
 	"fmt"
 	"log"
 	"net"
@@ -63,67 +61,6 @@ func shutdownServer(s *http.Server) {
 	s.Shutdown(ctx)
 }
 
-func parsePath(r *http.Request) (string, processingOptions, error) {
-	var po processingOptions
-	var err error
-
-	path := r.URL.Path
-	parts := strings.Split(strings.TrimPrefix(path, "/"), "/")
-
-	if len(parts) < 7 {
-		return "", po, errors.New("Invalid path")
-	}
-
-	token := parts[0]
-
-	if err = validatePath(token, strings.TrimPrefix(path, fmt.Sprintf("/%s", token))); err != nil {
-		return "", po, err
-	}
-
-	if r, ok := resizeTypes[parts[1]]; ok {
-		po.Resize = r
-	} else {
-		return "", po, fmt.Errorf("Invalid resize type: %s", parts[1])
-	}
-
-	if po.Width, err = strconv.Atoi(parts[2]); err != nil {
-		return "", po, fmt.Errorf("Invalid width: %s", parts[2])
-	}
-
-	if po.Height, err = strconv.Atoi(parts[3]); err != nil {
-		return "", po, fmt.Errorf("Invalid height: %s", parts[3])
-	}
-
-	if g, ok := gravityTypes[parts[4]]; ok {
-		po.Gravity = g
-	} else {
-		return "", po, fmt.Errorf("Invalid gravity: %s", parts[4])
-	}
-
-	po.Enlarge = parts[5] != "0"
-
-	filenameParts := strings.Split(strings.Join(parts[6:], ""), ".")
-
-	if len(filenameParts) < 2 {
-		po.Format = imageTypes["jpg"]
-	} else if f, ok := imageTypes[filenameParts[1]]; ok {
-		po.Format = f
-	} else {
-		return "", po, fmt.Errorf("Invalid image format: %s", filenameParts[1])
-	}
-
-	if !vipsTypeSupportSave[po.Format] {
-		return "", po, errors.New("Resulting image type not supported")
-	}
-
-	filename, err := base64.RawURLEncoding.DecodeString(filenameParts[0])
-	if err != nil {
-		return "", po, errors.New("Invalid filename encoding")
-	}
-
-	return string(filename), po, nil
-}
-
 func logResponse(status int, msg string) {
 	var color int