...

Source file src/github.com/go-openapi/runtime/middleware/negotiate.go

Documentation: github.com/go-openapi/runtime/middleware

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file or at
     5  // https://developers.google.com/open-source/licenses/bsd.
     6  
     7  // this file was taken from the github.com/golang/gddo repository
     8  
     9  package middleware
    10  
    11  import (
    12  	"net/http"
    13  	"strings"
    14  
    15  	"github.com/go-openapi/runtime/middleware/header"
    16  )
    17  
    18  // NegotiateContentEncoding returns the best offered content encoding for the
    19  // request's Accept-Encoding header. If two offers match with equal weight and
    20  // then the offer earlier in the list is preferred. If no offers are
    21  // acceptable, then "" is returned.
    22  func NegotiateContentEncoding(r *http.Request, offers []string) string {
    23  	bestOffer := "identity"
    24  	bestQ := -1.0
    25  	specs := header.ParseAccept(r.Header, "Accept-Encoding")
    26  	for _, offer := range offers {
    27  		for _, spec := range specs {
    28  			if spec.Q > bestQ &&
    29  				(spec.Value == "*" || spec.Value == offer) {
    30  				bestQ = spec.Q
    31  				bestOffer = offer
    32  			}
    33  		}
    34  	}
    35  	if bestQ == 0 {
    36  		bestOffer = ""
    37  	}
    38  	return bestOffer
    39  }
    40  
    41  // NegotiateContentType returns the best offered content type for the request's
    42  // Accept header. If two offers match with equal weight, then the more specific
    43  // offer is preferred.  For example, text/* trumps */*. If two offers match
    44  // with equal weight and specificity, then the offer earlier in the list is
    45  // preferred. If no offers match, then defaultOffer is returned.
    46  func NegotiateContentType(r *http.Request, offers []string, defaultOffer string) string {
    47  	bestOffer := defaultOffer
    48  	bestQ := -1.0
    49  	bestWild := 3
    50  	specs := header.ParseAccept(r.Header, "Accept")
    51  	for _, rawOffer := range offers {
    52  		offer := normalizeOffer(rawOffer)
    53  		// No Accept header: just return the first offer.
    54  		if len(specs) == 0 {
    55  			return rawOffer
    56  		}
    57  		for _, spec := range specs {
    58  			switch {
    59  			case spec.Q == 0.0:
    60  				// ignore
    61  			case spec.Q < bestQ:
    62  				// better match found
    63  			case spec.Value == "*/*":
    64  				if spec.Q > bestQ || bestWild > 2 {
    65  					bestQ = spec.Q
    66  					bestWild = 2
    67  					bestOffer = rawOffer
    68  				}
    69  			case strings.HasSuffix(spec.Value, "/*"):
    70  				if strings.HasPrefix(offer, spec.Value[:len(spec.Value)-1]) &&
    71  					(spec.Q > bestQ || bestWild > 1) {
    72  					bestQ = spec.Q
    73  					bestWild = 1
    74  					bestOffer = rawOffer
    75  				}
    76  			default:
    77  				if spec.Value == offer &&
    78  					(spec.Q > bestQ || bestWild > 0) {
    79  					bestQ = spec.Q
    80  					bestWild = 0
    81  					bestOffer = rawOffer
    82  				}
    83  			}
    84  		}
    85  	}
    86  	return bestOffer
    87  }
    88  
    89  func normalizeOffers(orig []string) (norm []string) {
    90  	for _, o := range orig {
    91  		norm = append(norm, normalizeOffer(o))
    92  	}
    93  	return
    94  }
    95  
    96  func normalizeOffer(orig string) string {
    97  	return strings.SplitN(orig, ";", 2)[0]
    98  }
    99  

View as plain text