Home Download Docs Code Community
     1	/*
     2	Copyright 2011 The Perkeep Authors
     3	
     4	Licensed under the Apache License, Version 2.0 (the "License");
     5	you may not use this file except in compliance with the License.
     6	You may obtain a copy of the License at
     7	
     8	     http://www.apache.org/licenses/LICENSE-2.0
     9	
    10	Unless required by applicable law or agreed to in writing, software
    11	distributed under the License is distributed on an "AS IS" BASIS,
    12	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13	See the License for the specific language governing permissions and
    14	limitations under the License.
    15	*/
    16	
    17	package handlers
    18	
    19	import (
    20		"fmt"
    21		"log"
    22		"net/http"
    23	
    24		"perkeep.org/internal/httputil"
    25		"perkeep.org/pkg/blob"
    26		"perkeep.org/pkg/blobserver"
    27	)
    28	
    29	const maxRemovesPerRequest = 1000
    30	
    31	func CreateRemoveHandler(storage blobserver.Storage) http.Handler {
    32		return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
    33			handleRemove(rw, req, storage)
    34		})
    35	}
    36	
    37	// RemoveResponse is the JSON response to a remove request.
    38	type RemoveResponse struct {
    39		Removed []blob.Ref `json:"removed"` // Refs of the removed blobs.
    40		Error   string     `json:"error"`
    41	}
    42	
    43	func handleRemove(w http.ResponseWriter, r *http.Request, storage blobserver.Storage) {
    44		ctx := r.Context()
    45		if r.Method != "POST" {
    46			log.Fatalf("Invalid method; handlers misconfigured")
    47		}
    48	
    49		configer, ok := storage.(blobserver.Configer)
    50		if !ok {
    51			msg := fmt.Sprintf("remove handler's blobserver.Storage isn't a blobserver.Configer, but a %T; can't remove", storage)
    52			log.Printf("blobserver/handlers: %v", msg)
    53			httputil.ReturnJSONCode(w, http.StatusForbidden, RemoveResponse{Error: msg})
    54			return
    55		}
    56		if !configer.Config().Deletable {
    57			msg := fmt.Sprintf("storage %T does not permit deletes", storage)
    58			log.Printf("blobserver/handlers: %v", msg)
    59			httputil.ReturnJSONCode(w, http.StatusForbidden, RemoveResponse{Error: msg})
    60			return
    61		}
    62	
    63		n := 0
    64		toRemove := make([]blob.Ref, 0)
    65		for {
    66			n++
    67			if n > maxRemovesPerRequest {
    68				httputil.BadRequestError(w,
    69					fmt.Sprintf("Too many removes in this request; max is %d", maxRemovesPerRequest))
    70				return
    71			}
    72			key := fmt.Sprintf("blob%v", n)
    73			value := r.FormValue(key)
    74			if value == "" {
    75				break
    76			}
    77			ref, ok := blob.Parse(value)
    78			if !ok {
    79				httputil.BadRequestError(w, "Bogus blobref for key "+key)
    80				return
    81			}
    82			toRemove = append(toRemove, ref)
    83		}
    84	
    85		err := storage.RemoveBlobs(ctx, toRemove)
    86		if err != nil {
    87			w.WriteHeader(http.StatusInternalServerError)
    88			log.Printf("Server error during remove: %v", err)
    89			fmt.Fprintf(w, "Server error")
    90			return
    91		}
    92	
    93		httputil.ReturnJSON(w, &RemoveResponse{Removed: toRemove})
    94	}
Website layout inspired by memcached.
Content by the authors.