Validate validates a route expression by ensuring that the route parameters can be inferred from the method payload and there is no duplicate parameters in an absolute route.
()
| 999 | // can be inferred from the method payload and there is no duplicate parameters |
| 1000 | // in an absolute route. |
| 1001 | func (r *RouteExpr) Validate() *eval.ValidationErrors { |
| 1002 | verr := new(eval.ValidationErrors) |
| 1003 | |
| 1004 | // Make sure route params are defined in the method payload |
| 1005 | if rparams := r.Params(); len(rparams) > 0 { |
| 1006 | if r.Endpoint.MethodExpr.Payload == nil { |
| 1007 | verr.Add(r, "Route parameters are defined, but method payload is not defined.") |
| 1008 | } else { |
| 1009 | switch r.Endpoint.MethodExpr.Payload.Type.(type) { |
| 1010 | case *Map: |
| 1011 | verr.Add(r, "Route parameters are defined, but method payload is a map. Method payload must be a primitive or an object.") |
| 1012 | case *Object, UserType: |
| 1013 | for _, p := range rparams { |
| 1014 | if r.Endpoint.MethodExpr.Payload.Find(p) == nil { |
| 1015 | verr.Add(r, "Route param %q not found in method payload", p) |
| 1016 | } |
| 1017 | } |
| 1018 | } |
| 1019 | if len(rparams) > 1 && IsPrimitive(r.Endpoint.MethodExpr.Payload.Type) { |
| 1020 | verr.Add(r, "Multiple route parameters are defined, but method payload is a primitive. Only one router parameter can be defined if payload is primitive.") |
| 1021 | } |
| 1022 | } |
| 1023 | } |
| 1024 | |
| 1025 | // Make sure there's no duplicate params in absolute route |
| 1026 | paths := r.FullPaths() |
| 1027 | for _, path := range paths { |
| 1028 | matches := HTTPWildcardRegex.FindAllStringSubmatch(path, -1) |
| 1029 | wcs := make(map[string]struct{}, len(matches)) |
| 1030 | for _, match := range matches { |
| 1031 | if _, ok := wcs[match[1]]; ok { |
| 1032 | verr.Add(r, "Wildcard %q appears multiple times in full path %q", match[1], path) |
| 1033 | } |
| 1034 | wcs[match[1]] = struct{}{} |
| 1035 | } |
| 1036 | } |
| 1037 | |
| 1038 | // For WebSocket streaming endpoints, only GET is supported |
| 1039 | // SSE endpoints can use both GET and POST (JSON-RPC SSE uses POST) |
| 1040 | if r.Endpoint.MethodExpr.IsStreaming() && len(r.Endpoint.Responses) > 0 && r.Endpoint.SSE == nil { |
| 1041 | if r.Method != "GET" { |
| 1042 | verr.Add(r, "WebSocket endpoint supports only \"GET\" method. Got %q.", r.Method) |
| 1043 | } |
| 1044 | } |
| 1045 | |
| 1046 | // HEAD method must not return a response body as per RFC 2616 section 9.4 |
| 1047 | if r.Method == "HEAD" { |
| 1048 | disallowBody := func(resp *HTTPResponseExpr) { |
| 1049 | if httpResponseBody(r.Endpoint, resp).Type != Empty { |
| 1050 | verr.Add(r, "HTTP status %d: Response body defined for HEAD method which does not allow response body.", resp.StatusCode) |
| 1051 | } |
| 1052 | } |
| 1053 | for _, resp := range r.Endpoint.Responses { |
| 1054 | disallowBody(resp) |
| 1055 | } |
| 1056 | for _, e := range r.Endpoint.HTTPErrors { |
| 1057 | disallowBody(e.Response) |
| 1058 | } |
nothing calls this directly
no test coverage detected