func()

in api/internal/handler/route/route.go [419:529]


func (h *Handler) Update(c droplet.Context) (interface{}, error) {
	input := c.Input().(*UpdateInput)

	// check if ID in body is equal ID in path
	if err := handler.IDCompare(input.ID, input.Route.ID); err != nil {
		return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err
	}

	// if has id in path, use it
	if input.ID != "" {
		input.Route.ID = input.ID
	}

	//check depend
	if input.ServiceID != nil {
		serviceID := utils.InterfaceToString(input.ServiceID)
		_, err := h.svcStore.Get(c.Context(), serviceID)
		if err != nil {
			if err == data.ErrNotFound {
				return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest},
					fmt.Errorf(consts.IDNotFound, "service", input.ServiceID)
			}
			return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err
		}
	}
	if input.UpstreamID != nil {
		upstreamID := utils.InterfaceToString(input.UpstreamID)
		_, err := h.upstreamStore.Get(c.Context(), upstreamID)
		if err != nil {
			if err == data.ErrNotFound {
				return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest},
					fmt.Errorf("upstream id: %s not found", input.UpstreamID)
			}
			return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err
		}
	}

	// If route's script_id is set, it must be equals to the route's id.
	if input.Route.ScriptID != nil && (utils.InterfaceToString(input.ID) != utils.InterfaceToString(input.Route.ScriptID)) {
		return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest},
			fmt.Errorf("script_id must be the same as id")
	}

	if input.Script != nil {
		script := &entity.Script{}
		script.ID = input.ID
		script.Script = input.Script

		var err error
		// Explicitly to lua if input script is of the map type, otherwise
		// it will always represent a piece of lua code of the string type.
		if scriptConf, ok := input.Script.(map[string]interface{}); ok {
			// For lua code of map type, syntax validation is done by
			// the generateLuaCode function
			input.Route.Script, err = generateLuaCode(scriptConf)
			if err != nil {
				return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err
			}
		} else {
			// For lua code of string type, use utility func to syntax validation
			err = utils.ValidateLuaCode(input.Script.(string))
			if err != nil {
				return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err
			}
		}

		//save original conf
		if _, err = h.scriptStore.Update(c.Context(), script, true); err != nil {
			//if not exists, create
			if err.Error() == fmt.Sprintf("key: %s is not found", script.ID) {
				if _, err := h.scriptStore.Create(c.Context(), script); err != nil {
					return handler.SpecCodeResponse(err), err
				}
			} else {
				return handler.SpecCodeResponse(err), err
			}
		}

		// After updating the Script entity, always set route's script_id
		// the same as route's id.
		input.Route.ScriptID = input.ID
	} else {
		// If script is unset, script_id must be unset neither.
		if input.Route.ScriptID != nil {
			return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest},
				fmt.Errorf("script_id cannot be set if script is unset")
		}
		//remove exists script
		id := utils.InterfaceToString(input.Route.ID)
		script, _ := h.scriptStore.Get(c.Context(), id)
		if script != nil {
			if err := h.scriptStore.BatchDelete(c.Context(), strings.Split(id, ",")); err != nil {
				log.Warnf("delete script %s failed", input.Route.ID)
			}
		}
	}

	// check name existed
	ret, err := handler.NameExistCheck(c.Context(), h.routeStore, "route", input.Name, input.ID)
	if err != nil {
		return ret, err
	}

	// create
	res, err := h.routeStore.Update(c.Context(), &input.Route, true)
	if err != nil {
		return handler.SpecCodeResponse(err), err
	}

	return res, nil
}