func filterParamsFromRequest()

in registry/handlers/repositories.go [387:493]


func filterParamsFromRequest(r *http.Request) (datastore.FilterParams, error) {
	var filters datastore.FilterParams

	q := r.URL.Query()
	maxEntries := defaultMaximumReturnedEntries
	if q.Has(nQueryParamKey) {
		val, valid := isQueryParamTypeInt(q.Get(nQueryParamKey))
		if !valid {
			detail := v1.InvalidQueryParamTypeErrorDetail(nQueryParamKey, nQueryParamValidTypes)
			return filters, v1.ErrorCodeInvalidQueryParamType.WithDetail(detail)
		}
		if !isQueryParamIntValueInBetween(val, nQueryParamValueMin, nQueryParamValueMax) {
			detail := v1.InvalidQueryParamValueRangeErrorDetail(nQueryParamKey, nQueryParamValueMin, nQueryParamValueMax)
			return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
		}

		maxEntries = val
	}
	filters.MaxEntries = maxEntries

	// `last` and `before` are mutually exclusive
	if q.Has(lastQueryParamKey) && q.Has(beforeQueryParamKey) {
		detail := v1.MutuallyExclusiveParametersErrorDetail(lastQueryParamKey, beforeQueryParamKey)
		return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
	}

	var beforeEntry string
	if q.Has(beforeQueryParamKey) {
		beforeEntry = q.Get(beforeQueryParamKey)
		// check if entry is base64 encoded, when is not, an error will be returned so we can ignore and continue
		publishedAt, tagName, err := DecodeFilter(beforeEntry)
		// if we assume we decoded the beforeEntry value successfully then the resulting publishedAt parameter
		// must be a date, otherwise the value of beforeEntry should be used in its raw form (i.e as a tag name)
		if err == nil && queryParamValueMatchesPattern(publishedAt, timestampRegexParam) {
			beforeEntry = tagName
			filters.PublishedAt = publishedAt
		}

		if !queryParamValueMatchesPattern(beforeEntry, tagQueryParamPattern) {
			detail := v1.InvalidQueryParamValuePatternErrorDetail(beforeQueryParamKey, tagQueryParamPattern)
			return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
		}
	}
	filters.BeforeEntry = beforeEntry

	// `lastEntry` must conform to the tag name regexp
	var lastEntry string
	if q.Has(lastQueryParamKey) {
		lastEntry = q.Get(lastQueryParamKey)
		// check if entry is base64 encoded, when is not, an error will be returned so we can ignore and continue
		publishedAt, tagName, err := DecodeFilter(lastEntry)
		// if we assume we decoded the lastEntry value successfully then the resulting publishedAt parameter
		// must be a date, otherwise the value of lastEntry should be used in its raw form (i.e as a tag name)
		if err == nil && queryParamValueMatchesPattern(publishedAt, timestampRegexParam) {
			lastEntry = tagName
			filters.PublishedAt = publishedAt
		}

		if !queryParamValueMatchesPattern(lastEntry, tagQueryParamPattern) {
			detail := v1.InvalidQueryParamValuePatternErrorDetail(lastQueryParamKey, tagQueryParamPattern)
			return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
		}
	}
	filters.LastEntry = lastEntry

	// `name` and `name_exact` are mutually exclusive
	if q.Has(tagNameQueryParamKey) && q.Has(tagExactNameQueryParamKey) {
		detail := v1.MutuallyExclusiveParametersErrorDetail(tagNameQueryParamKey, tagExactNameQueryParamKey)
		return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
	}

	nameFilter := tagNameQueryParamValue(r)
	if nameFilter != "" {
		if !queryParamValueMatchesPattern(nameFilter, tagNameQueryParamPattern) {
			detail := v1.InvalidQueryParamValuePatternErrorDetail(tagNameQueryParamKey, tagNameQueryParamPattern)
			return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
		}
	}
	filters.Name = nameFilter

	exactNameFilter := tagExactNameQueryParamValue(r)
	if exactNameFilter != "" {
		if !queryParamValueMatchesPattern(exactNameFilter, tagQueryParamPattern) {
			detail := v1.InvalidQueryParamValuePatternErrorDetail(tagExactNameQueryParamKey, tagQueryParamPattern)
			return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
		}
	}
	filters.ExactName = exactNameFilter

	sort := sortQueryParamValue(q)
	if sort != "" {
		if !isQueryParamValueValid(sort, sortQueryParamValidValues) {
			detail := v1.InvalidQueryParamValueErrorDetail(sortQueryParamKey, sortQueryParamValidValues)
			return filters, v1.ErrorCodeInvalidQueryParamValue.WithDetail(detail)
		}

		filters.OrderBy, filters.SortOrder = getSortOrderParams(sort)
	}

	if q.Has(referrersQueryParamKey) && q.Get(referrersQueryParamKey) == "true" {
		filters.IncludeReferrers = true
	}

	filters.ReferrerTypes = referrerTypeQueryParamValue(q)

	return filters, nil
}