github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/httpcontext/model.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package httpcontext
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"net/http"
    10  
    11  	"gopkg.in/juju/names.v2"
    12  )
    13  
    14  // ImpliedModelHandler is an http.Handler that associates requests that
    15  // it handles with a specified model UUID. The model UUID can then be
    16  // extracted using the RequestModel function in this package.
    17  type ImpliedModelHandler struct {
    18  	http.Handler
    19  	ModelUUID string
    20  }
    21  
    22  // ServeHTTP is part of the http.Handler interface.
    23  func (h *ImpliedModelHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    24  	ctx := context.WithValue(req.Context(), modelKey{}, h.ModelUUID)
    25  	req = req.WithContext(ctx)
    26  	h.Handler.ServeHTTP(w, req)
    27  }
    28  
    29  // QueryModelHandler is an http.Handler that associates requests that
    30  // it handles with a model UUID extracted from a specified query parameter.
    31  // The model UUID can then be extracted using the RequestModel function
    32  // in this package.
    33  type QueryModelHandler struct {
    34  	http.Handler
    35  	Query string
    36  }
    37  
    38  // ServeHTTP is part of the http.Handler interface.
    39  func (h *QueryModelHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    40  	modelUUID := req.URL.Query().Get(h.Query)
    41  	if modelUUID != "" {
    42  		if !names.IsValidModel(modelUUID) {
    43  			http.Error(w,
    44  				fmt.Sprintf("invalid model UUID %q", modelUUID),
    45  				http.StatusBadRequest,
    46  			)
    47  			return
    48  		}
    49  		ctx := context.WithValue(req.Context(), modelKey{}, modelUUID)
    50  		req = req.WithContext(ctx)
    51  	}
    52  	h.Handler.ServeHTTP(w, req)
    53  }
    54  
    55  type modelKey struct{}
    56  
    57  // RequestModelUUID returns the model UUID associated with this request
    58  // if there is one, or the empty string otherwise. No attempt is made
    59  // to validate the model UUID; QueryModelHandler does this, and
    60  // ImpliedModelHandler should always be supplied with a valid UUID.
    61  func RequestModelUUID(req *http.Request) string {
    62  	if value := req.Context().Value(modelKey{}); value != nil {
    63  		return value.(string)
    64  	}
    65  	return ""
    66  }