Skip to content

Commit

Permalink
Path validation respects path parameters
Browse files Browse the repository at this point in the history
Remove path uniqueness validation behavior where path parameters are
ignored.

Signed-off-by: Alex Dadgar <alex.dadgar@gmail.com>
  • Loading branch information
dadgar committed Oct 13, 2023
1 parent 348543c commit 48f320a
Show file tree
Hide file tree
Showing 4 changed files with 0 additions and 67 deletions.
18 changes: 0 additions & 18 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,6 @@ type pathHelper struct {
// A collection of unexported helpers for path validation
}

func (h *pathHelper) stripParametersInPath(path string) string {
// Returns a path stripped from all path parameters, with multiple or trailing slashes removed.
//
// Stripping is performed on a slash-separated basis, e.g '/a{/b}' remains a{/b} and not /a.
// - Trailing "/" make a difference, e.g. /a/ !~ /a (ex: canary/bitbucket.org/swagger.json)
// - presence or absence of a parameter makes a difference, e.g. /a/{log} !~ /a/ (ex: canary/kubernetes/swagger.json)

// Regexp to extract parameters from path, with surrounding {}.
// NOTE: important non-greedy modifier
rexParsePathParam := mustCompileRegexp(`{[^{}]+?}`)
strippedSegments := []string{}

for _, segment := range strings.Split(path, "/") {
strippedSegments = append(strippedSegments, rexParsePathParam.ReplaceAllString(segment, "X"))
}
return strings.Join(strippedSegments, "/")
}

func (h *pathHelper) extractPathParams(path string) (params []string) {
// Extracts all params from a path, with surrounding "{}"
rexParsePathParam := mustCompileRegexp(`{[^{}]+?}`)
Expand Down
29 changes: 0 additions & 29 deletions spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,44 +612,15 @@ func (s *SpecValidator) validateRequiredProperties(path, in string, v *spec.Sche
}

func (s *SpecValidator) validateParameters() *Result {
// - for each method, path is unique, regardless of path parameters
// e.g. GET:/petstore/{id}, GET:/petstore/{pet}, GET:/petstore are
// considered duplicate paths
// - each parameter should have a unique `name` and `type` combination
// - each operation should have only 1 parameter of type body
// - there must be at most 1 parameter in body
// - parameters with pattern property must specify valid patterns
// - $ref in parameters must resolve
// - path param must be required
res := new(Result)
rexGarbledPathSegment := mustCompileRegexp(`.*[{}\s]+.*`)
for method, pi := range s.expandedAnalyzer().Operations() {
methodPaths := make(map[string]map[string]string)
for path, op := range pi {
pathToAdd := pathHelp.stripParametersInPath(path)

// Warn on garbled path afer param stripping
if rexGarbledPathSegment.MatchString(pathToAdd) {
res.AddWarnings(pathStrippedParamGarbledMsg(pathToAdd))
}

// Check uniqueness of stripped paths
if _, found := methodPaths[method][pathToAdd]; found {

// Sort names for stable, testable output
if strings.Compare(path, methodPaths[method][pathToAdd]) < 0 {
res.AddErrors(pathOverlapMsg(path, methodPaths[method][pathToAdd]))
} else {
res.AddErrors(pathOverlapMsg(methodPaths[method][pathToAdd], path))
}
} else {
if _, found := methodPaths[method]; !found {
methodPaths[method] = map[string]string{}
}
methodPaths[method][pathToAdd] = path // Original non stripped path

}

var bodyParams []string
var paramNames []string
var hasForm, hasBody bool
Expand Down
12 changes: 0 additions & 12 deletions spec_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,6 @@ const (
// NoValidResponseError indicates that no valid response description could be found for an operation
NoValidResponseError = "operation %q has no valid response"

// PathOverlapError ...
PathOverlapError = "path %s overlaps with %s"

// PathParamNotInPathError indicates that a parameter specified with in: path was not found in the path specification
PathParamNotInPathError = "path param %q is not present in path %q"

Expand Down Expand Up @@ -166,9 +163,6 @@ const (
// ParamValidationTypeMismatch indicates that parameter has validation which does not match its type
ParamValidationTypeMismatch = "validation keywords of parameter %q in path %q don't match its type %s"

// PathStrippedParamGarbledWarning ...
PathStrippedParamGarbledWarning = "path stripped from path parameters %s contains {,} or white space. This is probably no what you want."

// ReadOnlyAndRequiredWarning ...
ReadOnlyAndRequiredWarning = "Required property %s in %q should not be marked as both required and readOnly"

Expand Down Expand Up @@ -245,12 +239,6 @@ func requiredButNotDefinedMsg(path, definition string) errors.Error {
func pathParamGarbledMsg(path, param string) errors.Error {
return errors.New(errors.CompositeErrorCode, PathParamGarbledWarning, path, param)
}
func pathStrippedParamGarbledMsg(path string) errors.Error {
return errors.New(errors.CompositeErrorCode, PathStrippedParamGarbledWarning, path)
}
func pathOverlapMsg(path, arg string) errors.Error {
return errors.New(errors.CompositeErrorCode, PathOverlapError, path, arg)
}
func invalidPatternInParamMsg(operation, param, pattern string) errors.Error {
return errors.New(errors.CompositeErrorCode, InvalidPatternInParamError, operation, param, pattern)
}
Expand Down
8 changes: 0 additions & 8 deletions spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,14 +443,6 @@ func TestSpec_ValidateParameters(t *testing.T) {
pp.Parameters = nameParams
sw.Paths.Paths["/pets/{name}"] = pp

validator = NewSpecValidator(spec.MustLoadSwagger20Schema(), strfmt.Default)
validator.spec = doc
validator.analyzer = analysis.New(doc.Spec())
res = validator.validateParameters()
assert.NotEmpty(t, res.Errors)
assert.Len(t, res.Errors, 1)
assert.Contains(t, res.Errors[0].Error(), "overlaps with")

doc, _ = loads.Analyzed(PetStoreJSONMessage, "")
validator = NewSpecValidator(spec.MustLoadSwagger20Schema(), strfmt.Default)
validator.spec = doc
Expand Down

0 comments on commit 48f320a

Please sign in to comment.