package rest import "strings" // Enumeration of well-known content-types const ( ContentTypeApplicationJSON = "application/json" ) // ContentType defines a media type and is composed of a type, a subtype (and // optional suffix), and optional parameters. type ContentType struct { Type string Subtype string // including tree Suffix string Parameters map[string]string } // ParseContentType splits a content-type string into its parts. // // top-level type name / subtype name [ ; parameters ] // top-level type name / [ tree. ] subtype name [ +suffix ] [ ; parameters ] func ParseContentType(s string) ContentType { ct := ContentType{} // Top-level type name parts := strings.SplitN(s, "/", 2) // required if len(parts) != 2 { return ct } if parts[1] == "" { return ct } ct.Type = strings.TrimSpace(parts[0]) // Subtype name sParts := strings.SplitN(parts[1], ";", -1) // optional if len(sParts) == 0 { return ct } if sParts[0] == "" { return ct } ssParts := strings.SplitN(sParts[0], "+", 2) // optional if len(ssParts) == 0 { return ct } if ssParts[0] == "" { return ct } ct.Subtype = strings.TrimSpace(ssParts[0]) // Optional suffix if len(ssParts) == 2 { ct.Suffix = strings.TrimSpace(ssParts[1]) } // Optional parameters params := map[string]string{} for _, param := range sParts[1:] { pParts := strings.SplitN(param, "=", 2) if len(pParts) == 2 { key := strings.TrimSpace(pParts[0]) params[key] = strings.TrimSpace(pParts[1]) } else if len(pParts) == 1 { key := strings.TrimSpace(pParts[0]) params[key] = "" } } if len(params) > 0 { ct.Parameters = params } return ct }