func compilePath(t *testing.T, path string) httprule.Template {
	parsed, err := httprule.Parse(path)
	if err != nil {
		t.Fatalf("httprule.Parse(%q) failed with %v; want success", path, err)
	}
	return parsed.Compile()
}
Exemple #2
0
func (r *Registry) newMethod(svc *Service, md *descriptor.MethodDescriptorProto, opts *options.HttpRule) (*Method, error) {
	requestType, err := r.LookupMsg(svc.File.GetPackage(), md.GetInputType())
	if err != nil {
		return nil, err
	}
	responseType, err := r.LookupMsg(svc.File.GetPackage(), md.GetOutputType())
	if err != nil {
		return nil, err
	}
	meth := &Method{
		Service:               svc,
		MethodDescriptorProto: md,
		RequestType:           requestType,
		ResponseType:          responseType,
	}

	newBinding := func(opts *options.HttpRule, idx int) (*Binding, error) {
		var (
			httpMethod   string
			pathTemplate string
		)
		switch {
		case opts.Get != "":
			httpMethod = "GET"
			pathTemplate = opts.Get
			if opts.Body != "" {
				return nil, fmt.Errorf("needs request body even though http method is GET: %s", md.GetName())
			}

		case opts.Put != "":
			httpMethod = "PUT"
			pathTemplate = opts.Put

		case opts.Post != "":
			httpMethod = "POST"
			pathTemplate = opts.Post

		case opts.Delete != "":
			httpMethod = "DELETE"
			pathTemplate = opts.Delete
			if opts.Body != "" {
				return nil, fmt.Errorf("needs request body even though http method is DELETE: %s", md.GetName())
			}

		case opts.Patch != "":
			httpMethod = "PATCH"
			pathTemplate = opts.Patch

		case opts.Custom != nil:
			httpMethod = opts.Custom.Kind
			pathTemplate = opts.Custom.Path

		default:
			glog.Errorf("No pattern specified in google.api.HttpRule: %s", md.GetName())
			return nil, fmt.Errorf("none of pattern specified")
		}

		parsed, err := httprule.Parse(pathTemplate)
		if err != nil {
			return nil, err
		}
		tmpl := parsed.Compile()

		if md.GetClientStreaming() && len(tmpl.Fields) > 0 {
			return nil, fmt.Errorf("cannot use path parameter in client streaming")
		}

		b := &Binding{
			Method:     meth,
			Index:      idx,
			PathTmpl:   tmpl,
			HTTPMethod: httpMethod,
		}

		for _, f := range tmpl.Fields {
			param, err := r.newParam(meth, f)
			if err != nil {
				return nil, err
			}
			b.PathParams = append(b.PathParams, param)
		}

		// TODO(yugui) Handle query params

		b.Body, err = r.newBody(meth, opts.Body)
		if err != nil {
			return nil, err
		}

		return b, nil
	}
	b, err := newBinding(opts, 0)
	if err != nil {
		return nil, err
	}

	meth.Bindings = append(meth.Bindings, b)
	for i, additional := range opts.GetAdditionalBindings() {
		if len(additional.AdditionalBindings) > 0 {
			return nil, fmt.Errorf("additional_binding in additional_binding not allowed: %s.%s", svc.GetName(), meth.GetName())
		}
		b, err := newBinding(additional, i+1)
		if err != nil {
			return nil, err
		}
		meth.Bindings = append(meth.Bindings, b)
	}

	return meth, nil
}