func FromCloudFunction()

in wstl1/mapping_engine/cloudfunction/cloudfunction.go [57:115]


func FromCloudFunction(cf *httppb.CloudFunction) (types.Projector, error) {
	if err := validateCloudFunction(cf); err != nil {
		return nil, fmt.Errorf("invalid Google cloud function definition: %v", err)
	}
	return func(metaArgs []jsonutil.JSONMetaNode, pctx *types.Context) (jsonutil.JSONToken, error) {
		errLocation := errs.FnLocationf("Cloud Function Preamble %q", cf.Name)

		args := make([]jsonutil.JSONToken, len(metaArgs))
		for i, metaArg := range metaArgs {
			node, err := jsonutil.NodeToToken(metaArg)
			if err != nil {
				return nil, errs.Wrap(errLocation, fmt.Errorf("error converting args: %v", err))
			}
			args[i] = node
		}

		var body []byte
		var err error

		if len(args) == 1 {
			body, err = json.Marshal(args[0])
		} else {
			body, err = json.Marshal(args)
		}

		if err != nil {
			return nil, errs.Wrap(errLocation, fmt.Errorf("error marshaling arguments into a JSON object: %v", err))
		}

		errLocation = errs.FnLocationf("Cloud Function %q", cf.Name)

		resp, err := http.Post(cf.RequestUrl, "application/json", bytes.NewBuffer(body))
		if err != nil {
			return nil, errs.Wrap(errLocation, fmt.Errorf("cloud function request failed due to: %v", err))
		}

		if resp.StatusCode != http.StatusOK {
			message, _ := ioutil.ReadAll(resp.Body)
			return nil, errs.Wrap(errLocation, fmt.Errorf("error http response status code: %v, error message: %s", resp.Status, message))
		}

		defer resp.Body.Close()
		bytes, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, errs.Wrap(errLocation, fmt.Errorf("error reading http response body: %v", err))
		}

		if len(bytes) == 0 {
			return nil, errs.Wrap(errLocation, fmt.Errorf("error empty http response body"))
		}

		val, err := jsonutil.UnmarshalJSON(json.RawMessage(bytes))
		if err != nil {
			return nil, errs.Wrap(errLocation, fmt.Errorf("error unmarshal http response body into JSONToken: %v", err))
		}

		return val, nil
	}, nil
}