Beispiel #1
0
func negotiateOutputSerializer(req *http.Request, ns runtime.NegotiatedSerializer) (runtime.Serializer, string, error) {
	acceptHeader := req.Header.Get("Accept")
	supported := ns.SupportedMediaTypes()
	if len(acceptHeader) == 0 && len(supported) > 0 {
		acceptHeader = supported[0]
	}
	accept, ok := negotiate(acceptHeader, supported)
	if !ok {
		return nil, "", errNotAcceptable{supported}
	}

	pretty := isPrettyPrint(req)
	if _, ok := accept.Params["pretty"]; !ok && pretty {
		accept.Params["pretty"] = "1"
	}
	mediaType := accept.Type
	if len(accept.SubType) > 0 {
		mediaType += "/" + accept.SubType
	}
	if s, ok := ns.SerializerForMediaType(mediaType, accept.Params); ok {
		return s, mediaType, nil
	}

	return nil, "", errNotAcceptable{supported}
}
Beispiel #2
0
// Adds a service to return the supported resources, E.g., a such web service
// will be registered at /apis/extensions/v1.
func AddSupportedResourcesWebService(s runtime.NegotiatedSerializer, ws *restful.WebService, groupVersion unversioned.GroupVersion, apiResources []unversioned.APIResource) {
	resourceHandler := SupportedResourcesHandler(s, groupVersion, apiResources)
	ws.Route(ws.GET("/").To(resourceHandler).
		Doc("get available resources").
		Operation("getAPIResources").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
}
// mediaTypesForSerializer returns a list of media and stream media types for the server.
func mediaTypesForSerializer(ns runtime.NegotiatedSerializer) (mediaTypes, streamMediaTypes []string) {
	for _, info := range ns.SupportedMediaTypes() {
		mediaTypes = append(mediaTypes, info.MediaType)
		if info.StreamSerializer != nil {
			// stream=watch is the existing mime-type parameter for watch
			streamMediaTypes = append(streamMediaTypes, info.MediaType+";stream=watch")
		}
	}
	return mediaTypes, streamMediaTypes
}
Beispiel #4
0
func negotiateOutputStreamSerializer(req *http.Request, ns runtime.NegotiatedSerializer) (runtime.StreamSerializerInfo, error) {
	supported := ns.SupportedMediaTypes()
	mediaType, params, err := negotiateOutput(req, supported)
	if err != nil {
		return runtime.StreamSerializerInfo{}, err
	}
	if s, ok := ns.StreamingSerializerForMediaType(mediaType, params); ok {
		return s, nil
	}
	return runtime.StreamSerializerInfo{}, errNotAcceptable{supported}
}
Beispiel #5
0
func negotiateOutputStreamSerializer(req *http.Request, ns runtime.NegotiatedSerializer) (runtime.Serializer, runtime.Framer, string, string, error) {
	supported := ns.SupportedMediaTypes()
	mediaType, params, err := negotiateOutput(req, supported)
	if err != nil {
		return nil, nil, "", "", err
	}
	if s, f, exactMediaType, ok := ns.StreamingSerializerForMediaType(mediaType, params); ok {
		return s, f, mediaType, exactMediaType, nil
	}
	return nil, nil, "", "", errNotAcceptable{supported}
}
Beispiel #6
0
// Adds a service to return the supported versions, preferred version, and name
// of a group. E.g., a such web service will be registered at /apis/extensions.
func AddGroupWebService(s runtime.NegotiatedSerializer, container *restful.Container, path string, group unversioned.APIGroup) {
	groupHandler := GroupHandler(s, group)
	ws := new(restful.WebService)
	ws.Path(path)
	ws.Doc("get information of a group")
	ws.Route(ws.GET("/").To(groupHandler).
		Doc("get information of a group").
		Operation("getAPIGroup").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
	container.Add(ws)
}
Beispiel #7
0
// Adds a service to return the supported api versions at /apis.
func AddApisWebService(s runtime.NegotiatedSerializer, container *restful.Container, apiPrefix string, f func() []unversioned.APIGroup) {
	rootAPIHandler := RootAPIHandler(s, f)
	ws := new(restful.WebService)
	ws.Path(apiPrefix)
	ws.Doc("get available API versions")
	ws.Route(ws.GET("/").To(rootAPIHandler).
		Doc("get available API versions").
		Operation("getAPIVersions").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
	container.Add(ws)
}
Beispiel #8
0
// Adds a service to return the supported api versions at the legacy /api.
func AddApiWebService(s runtime.NegotiatedSerializer, container *restful.Container, apiPrefix string, versions []string) {
	// TODO: InstallREST should register each version automatically

	versionHandler := APIVersionHandler(s, versions[:]...)
	ws := new(restful.WebService)
	ws.Path(apiPrefix)
	ws.Doc("get available API versions")
	ws.Route(ws.GET("/").To(versionHandler).
		Doc("get available API versions").
		Operation("getAPIVersions").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
	container.Add(ws)
}
Beispiel #9
0
// Adds a service to return the supported resources, E.g., a such web service
// will be registered at /apis/extensions/v1.
func AddSupportedResourcesWebService(s runtime.NegotiatedSerializer, ws *restful.WebService, groupVersion unversioned.GroupVersion, apiResources []unversioned.APIResource) {
	ss := s
	if keepUnversioned(groupVersion.Group) {
		// Because in release 1.1, /apis/extensions/v1beta1 returns response
		// with empty APIVersion, we use StripVersionNegotiatedSerializer to
		// keep the response backwards compatible.
		ss = StripVersionNegotiatedSerializer{s}
	}
	resourceHandler := SupportedResourcesHandler(ss, groupVersion, apiResources)
	ws.Route(ws.GET("/").To(resourceHandler).
		Doc("get available resources").
		Operation("getAPIResources").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
}
Beispiel #10
0
func negotiateInputSerializer(req *http.Request, s runtime.NegotiatedSerializer) (runtime.SerializerInfo, error) {
	supported := s.SupportedMediaTypes()
	mediaType := req.Header.Get("Content-Type")
	if len(mediaType) == 0 {
		mediaType = supported[0]
	}
	mediaType, options, err := mime.ParseMediaType(mediaType)
	if err != nil {
		return runtime.SerializerInfo{}, errUnsupportedMediaType{supported}
	}
	out, ok := s.SerializerForMediaType(mediaType, options)
	if !ok {
		return runtime.SerializerInfo{}, errUnsupportedMediaType{supported}
	}
	return out, nil
}
// acceptedMediaTypesForEndpoint returns an array of structs that are used to efficiently check which
// allowed media types the server exposes.
func acceptedMediaTypesForEndpoint(ns runtime.NegotiatedSerializer) []acceptedMediaType {
	var acceptedMediaTypes []acceptedMediaType
	for _, info := range ns.SupportedMediaTypes() {
		segments := strings.SplitN(info.MediaType, "/", 2)
		if len(segments) == 1 {
			segments = append(segments, "*")
		}
		t := acceptedMediaType{
			Type:       segments[0],
			SubType:    segments[1],
			Serializer: info,
		}
		acceptedMediaTypes = append(acceptedMediaTypes, t)
	}
	return acceptedMediaTypes
}
Beispiel #12
0
// Adds a service to return the supported api versions at /apis.
func AddApisWebService(s runtime.NegotiatedSerializer, container *restful.Container, apiPrefix string, f func(req *restful.Request) []unversioned.APIGroup) {
	// Because in release 1.1, /apis returns response with empty APIVersion, we
	// use StripVersionNegotiatedSerializer to keep the response backwards
	// compatible.
	ss := StripVersionNegotiatedSerializer{s}
	rootAPIHandler := RootAPIHandler(ss, f)
	ws := new(restful.WebService)
	ws.Path(apiPrefix)
	ws.Doc("get available API versions")
	ws.Route(ws.GET("/").To(rootAPIHandler).
		Doc("get available API versions").
		Operation("getAPIVersions").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
	container.Add(ws)
}
Beispiel #13
0
// writeNegotiated renders an object in the content type negotiated by the client
func writeNegotiated(s runtime.NegotiatedSerializer, gv unversioned.GroupVersion, w http.ResponseWriter, req *http.Request, statusCode int, object runtime.Object) {
	serializer, contentType, err := negotiateOutputSerializer(req, s)
	if err != nil {
		status := errToAPIStatus(err)
		writeRawJSON(int(status.Code), status, w)
		return
	}

	w.Header().Set("Content-Type", contentType)
	w.WriteHeader(statusCode)

	encoder := s.EncoderForVersion(serializer, gv)
	if err := encoder.EncodeToStream(object, w); err != nil {
		errorJSONFatal(err, encoder, w)
	}
}
Beispiel #14
0
// Adds a service to return the supported api versions at the legacy /api.
func AddApiWebService(s runtime.NegotiatedSerializer, container *restful.Container, apiPrefix string, getAPIVersionsFunc func(req *restful.Request) *unversioned.APIVersions) {
	// TODO: InstallREST should register each version automatically

	// Because in release 1.1, /api returns response with empty APIVersion, we
	// use StripVersionNegotiatedSerializer to keep the response backwards
	// compatible.
	ss := StripVersionNegotiatedSerializer{s}
	versionHandler := APIVersionHandler(ss, getAPIVersionsFunc)
	ws := new(restful.WebService)
	ws.Path(apiPrefix)
	ws.Doc("get available API versions")
	ws.Route(ws.GET("/").To(versionHandler).
		Doc("get available API versions").
		Operation("getAPIVersions").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
	container.Add(ws)
}
Beispiel #15
0
// Adds a service to return the supported versions, preferred version, and name
// of a group. E.g., a such web service will be registered at /apis/extensions.
func AddGroupWebService(s runtime.NegotiatedSerializer, container *restful.Container, path string, group unversioned.APIGroup) {
	ss := s
	if keepUnversioned(group.Name) {
		// Because in release 1.1, /apis/extensions returns response with empty
		// APIVersion, we use StripVersionNegotiatedSerializer to keep the
		// response backwards compatible.
		ss = StripVersionNegotiatedSerializer{s}
	}
	groupHandler := GroupHandler(ss, group)
	ws := new(restful.WebService)
	ws.Path(path)
	ws.Doc("get information of a group")
	ws.Route(ws.GET("/").To(groupHandler).
		Doc("get information of a group").
		Operation("getAPIGroup").
		Produces(s.SupportedMediaTypes()...).
		Consumes(s.SupportedMediaTypes()...))
	container.Add(ws)
}
Beispiel #16
0
func newEtcd(ns runtime.NegotiatedSerializer, storageGroupVersionString, memoryGroupVersionString string, etcdConfig etcdstorage.EtcdConfig) (etcdStorage storage.Interface, err error) {
	if storageGroupVersionString == "" {
		return etcdStorage, fmt.Errorf("storageVersion is required to create a etcd storage")
	}
	storageVersion, err := unversioned.ParseGroupVersion(storageGroupVersionString)
	if err != nil {
		return nil, fmt.Errorf("couldn't understand storage version %v: %v", storageGroupVersionString, err)
	}
	memoryVersion, err := unversioned.ParseGroupVersion(memoryGroupVersionString)
	if err != nil {
		return nil, fmt.Errorf("couldn't understand memory version %v: %v", memoryGroupVersionString, err)
	}

	var storageConfig etcdstorage.EtcdStorageConfig
	storageConfig.Config = etcdConfig
	s, ok := ns.SerializerForMediaType("application/json", nil)
	if !ok {
		return nil, fmt.Errorf("unable to find serializer for JSON")
	}
	glog.Infof("constructing etcd storage interface.\n  sv: %v\n  mv: %v\n", storageVersion, memoryVersion)
	encoder := ns.EncoderForVersion(s, storageVersion)
	decoder := ns.DecoderToVersion(s, memoryVersion)
	if memoryVersion.Group != storageVersion.Group {
		// Allow this codec to translate between groups.
		if err = versioning.EnableCrossGroupEncoding(encoder, memoryVersion.Group, storageVersion.Group); err != nil {
			return nil, fmt.Errorf("error setting up encoder for %v: %v", storageGroupVersionString, err)
		}
		if err = versioning.EnableCrossGroupDecoding(decoder, storageVersion.Group, memoryVersion.Group); err != nil {
			return nil, fmt.Errorf("error setting up decoder for %v: %v", storageGroupVersionString, err)
		}
	}
	storageConfig.Codec = runtime.NewCodec(encoder, decoder)
	return storageConfig.NewStorage()
}
func negotiateInputSerializer(req *http.Request, ns runtime.NegotiatedSerializer) (runtime.SerializerInfo, error) {
	mediaTypes := ns.SupportedMediaTypes()
	mediaType := req.Header.Get("Content-Type")
	if len(mediaType) == 0 {
		mediaType = mediaTypes[0].MediaType
	}
	mediaType, _, err := mime.ParseMediaType(mediaType)
	if err != nil {
		_, supported := mediaTypesForSerializer(ns)
		return runtime.SerializerInfo{}, errUnsupportedMediaType{supported}
	}

	for _, info := range mediaTypes {
		if info.MediaType != mediaType {
			continue
		}
		return info, nil
	}

	_, supported := mediaTypesForSerializer(ns)
	return runtime.SerializerInfo{}, errUnsupportedMediaType{supported}
}
Beispiel #18
0
func newEtcd(etcdServerList []string, ns runtime.NegotiatedSerializer, storageGroupVersionString, pathPrefix string) (etcdStorage storage.Interface, err error) {
	if storageGroupVersionString == "" {
		return etcdStorage, fmt.Errorf("storageVersion is required to create a etcd storage")
	}
	storageVersion, err := unversioned.ParseGroupVersion(storageGroupVersionString)
	if err != nil {
		return nil, err
	}

	var storageConfig etcdstorage.EtcdConfig
	storageConfig.ServerList = etcdServerList
	storageConfig.Prefix = pathPrefix
	s, ok := ns.SerializerForMediaType("application/json", nil)
	if !ok {
		return nil, fmt.Errorf("unable to find serializer for JSON")
	}
	storageConfig.Codec = runtime.NewCodec(ns.EncoderForVersion(s, storageVersion), ns.DecoderToVersion(s, unversioned.GroupVersion{Group: storageVersion.Group, Version: runtime.APIVersionInternal}))
	return storageConfig.NewStorage()
}
Beispiel #19
0
func newEtcd(ns runtime.NegotiatedSerializer, storageVersion, memoryVersion unversioned.GroupVersion, config storagebackend.Config) (etcdStorage storage.Interface, err error) {
	s, ok := ns.SerializerForMediaType("application/json", nil)
	if !ok {
		return nil, fmt.Errorf("unable to find serializer for JSON")
	}
	encoder := ns.EncoderForVersion(s, storageVersion)
	decoder := ns.DecoderToVersion(s, memoryVersion)
	if memoryVersion.Group != storageVersion.Group {
		// Allow this codec to translate between groups.
		if err = versioning.EnableCrossGroupEncoding(encoder, memoryVersion.Group, storageVersion.Group); err != nil {
			return nil, fmt.Errorf("error setting up encoder from %v to %v: %v", memoryVersion, storageVersion, err)
		}
		if err = versioning.EnableCrossGroupDecoding(decoder, storageVersion.Group, memoryVersion.Group); err != nil {
			return nil, fmt.Errorf("error setting up decoder from %v to %v: %v", storageVersion, memoryVersion, err)
		}
	}
	config.Codec = runtime.NewCodec(encoder, decoder)
	return storagebackend.Create(config)
}