Beispiel #1
0
func Marshal(resp http.ResponseWriter, req *http.Request, value interface{}) error {
	contentType := ContentTypeForResponse(req)
	if t, err := encoding.ContentTypeFromString(contentType); err == nil {
		buff := new(bytes.Buffer)
		err := encoding.Marshal(t, buff, value)
		if err != nil {
			DefaultErrorRenderer(resp, req, err.Error(), http.StatusInternalServerError)
			return err
		}
		resp.Header().Add("Content-Type", t.String())
		resp.Write(buff.Bytes())
	} else {
		DefaultErrorRenderer(resp, req, ErrBadContentType.Error(), http.StatusBadRequest)
		return err
	}
	return nil
}
Beispiel #2
0
// Run the configuration specified in conf against the target.  This will run a series
// of template fetching, applying templates, unmarshaling of the final applied template
// onto the given target object.  After unmarshaling is done, the target's fields are
// examined one by one, by tag, and fields that have template as values are then applied.
func Configure(ctx context.Context, conf Conf, target interface{}, optionalFuncs ...template.FuncMap) error {
	conf.lock.Lock()
	defer conf.lock.Unlock()

	initialData := ContextGetInitialData(ctx)
	if initialData != nil {
		gtemplate.ContextPutTemplateData(ctx, initialData)
	}

	contentType := ContextGetConfigDataType(ctx)

	// Generate a list of functions that will escape the template strings
	// Ex.  "secret" : "{{var "zk://host/path/to/secret"}}"
	// This string will be escaped so that the evaluation happens after the unmarshal step by field tag
	funcs := template.FuncMap{}
	for _, fns := range optionalFuncs {
		funcs = gtemplate.MergeFuncMaps(funcs, fns)
	}

	// Note here we generate escaped versions of function to override what's provided.
	// The actual funcs are used in the struct field-by-field step, for those that are marked by tags.
	stubs := gtemplate.MergeFuncMaps(funcs, generateEscapeFuncsFromFieldTag(target))

	conf.model = map[string]interface{}{}
	for _, url := range conf.Urls {

		// Fetch the config data and execute as if it were template
		applied, err := gtemplate.Execute(ctx, url, stubs)

		if conf.OnDoneExecuteLayer != nil {
			conf.OnDoneExecuteLayer(&conf, url, applied, err)
		}

		if err != nil {
			return err
		}

		// Unmarshal to an intermediate representation
		buff := bytes.NewBuffer(applied)
		err = encoding.Unmarshal(contentType, buff, conf.model)

		if conf.OnDoneUnmarshalLayer != nil {
			conf.OnDoneUnmarshalLayer(&conf, url, err)
		}

		if err != nil {
			return err
		}
	}

	if conf.OnDoneFetching != nil {
		conf.OnDoneFetching(&conf)
	}

	// Now marshal the aggregated model to a buffer and then unmarshal it back to the typed struct
	serialized := new(bytes.Buffer)
	err := encoding.Marshal(contentType, serialized, conf.model)
	if err != nil {
		return err
	}
	conf.serialized = serialized.Bytes()
	err = encoding.Unmarshal(contentType, bytes.NewBuffer(conf.serialized), target)

	if conf.OnDoneSerialize != nil {
		conf.OnDoneSerialize(&conf, err)
	}

	if err != nil {
		return err
	}

	if conf.OnDoneUnmarshal != nil {
		conf.OnDoneUnmarshal(&conf, target)
	}

	// Now look for fields with struct tags and apply the actual templates
	return evalStructFieldTemplates(target, funcs)
}