Пример #1
0
        internal HttpMethodInfo(ServiceMethodInfo methodInfo, ServiceInfo serviceInfo)
        {
            ServiceMethod = methodInfo;

            Method = "POST";
            Path   = $"/{methodInfo.Name}";
            HttpStatusCode?statusCode = null;

            foreach (var methodParameter in GetHttpParameters(methodInfo))
            {
                if (methodParameter.Name == "method")
                {
                    Method = GetHttpMethodFromParameter(methodParameter);
                }
                else if (methodParameter.Name == "path")
                {
                    if (methodParameter.Value.Length == 0 || methodParameter.Value[0] != '/')
                    {
                        AddValidationError(new ServiceDefinitionError("'path' value must start with a slash.", methodParameter.GetPart(ServicePartKind.Value)?.Position));
                    }
                    Path = methodParameter.Value;
                }
                else if (methodParameter.Name == "code")
                {
                    statusCode = TryParseStatusCodeInteger(methodParameter);
                }
                else
                {
                    AddInvalidHttpParameterError(methodParameter);
                }
            }

            var pathParameterNames = new HashSet <string>(GetPathParameterNames(Path));

            var requestPathFields              = new List <HttpPathFieldInfo>();
            var requestQueryFields             = new List <HttpQueryFieldInfo>();
            var requestNormalFields            = new List <HttpNormalFieldInfo>();
            HttpBodyFieldInfo requestBodyField = null;
            var requestHeaderFields            = new List <HttpHeaderFieldInfo>();

            foreach (var requestField in methodInfo.RequestFields)
            {
                string from = requestField.TryGetHttpAttribute()?.TryGetParameterValue("from");
                if (from == "path")
                {
                    if (!IsValidSimpleField(requestField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by path field.", requestField.Position));
                    }
                    var pathInfo = new HttpPathFieldInfo(requestField);
                    if (!pathParameterNames.Remove(pathInfo.Name))
                    {
                        AddValidationError(new ServiceDefinitionError("Path request field has no placeholder in the method path.", requestField.Position));
                    }
                    requestPathFields.Add(pathInfo);
                }
                else if (from == "query")
                {
                    if (!IsValidSimpleField(requestField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by query field.", requestField.Position));
                    }
                    requestQueryFields.Add(new HttpQueryFieldInfo(requestField));
                }
                else if (from == "normal")
                {
                    if (IsNoContentMethod(Method))
                    {
                        AddValidationError(new ServiceDefinitionError($"HTTP {Method} does not support normal fields.", requestField.Position));
                    }
                    requestNormalFields.Add(new HttpNormalFieldInfo(requestField));
                }
                else if (from == "body")
                {
                    if (!IsValidRequestBodyField(requestField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by body request field.", requestField.Position));
                    }
                    if (requestBodyField != null)
                    {
                        AddValidationError(new ServiceDefinitionError("Requests do not support multiple body fields.", requestField.Position));
                    }
                    var bodyInfo = new HttpBodyFieldInfo(requestField);
                    if (bodyInfo.StatusCode != null)
                    {
                        AddValidationError(new ServiceDefinitionError("Request fields do not support status codes.", requestField.Position));
                    }
                    requestBodyField = bodyInfo;
                }
                else if (from == "header")
                {
                    if (!IsValidSimpleField(requestField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by header request field.", requestField.Position));
                    }
                    requestHeaderFields.Add(new HttpHeaderFieldInfo(requestField));
                }
                else if (from != null)
                {
                    AddValidationError(new ServiceDefinitionError($"Unsupported 'from' parameter of 'http' attribute: '{from}'", requestField.Position));
                }
                else if (pathParameterNames.Remove(requestField.Name))
                {
                    if (!IsValidSimpleField(requestField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by path field.", requestField.Position));
                    }
                    requestPathFields.Add(new HttpPathFieldInfo(requestField));
                }
                else if (Method == "GET" || Method == "DELETE")
                {
                    if (!IsValidSimpleField(requestField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by query field.", requestField.Position));
                    }
                    requestQueryFields.Add(new HttpQueryFieldInfo(requestField));
                }
                else
                {
                    requestNormalFields.Add(new HttpNormalFieldInfo(requestField));
                }
            }

            if (pathParameterNames.Count != 0)
            {
                AddValidationError(new ServiceDefinitionError($"Unused path parameter '{pathParameterNames.First()}'.", methodInfo.Position));
            }
            if (requestBodyField != null && requestNormalFields.Count != 0)
            {
                AddValidationError(new ServiceDefinitionError("A request cannot have a normal field and a body field.", requestBodyField.ServiceField.Position));
            }

            PathFields          = requestPathFields;
            QueryFields         = requestQueryFields;
            RequestNormalFields = requestNormalFields;
            RequestBodyField    = requestBodyField;
            RequestHeaderFields = requestHeaderFields;

            var responseNormalFields = new List <HttpNormalFieldInfo>();
            var responseBodyFields   = new List <HttpBodyFieldInfo>();
            var responseHeaderFields = new List <HttpHeaderFieldInfo>();

            foreach (var responseField in methodInfo.ResponseFields)
            {
                string from = responseField.TryGetHttpAttribute()?.TryGetParameterValue("from");
                if (from == "path" || from == "query")
                {
                    AddValidationError(new ServiceDefinitionError("Response fields must not be path or query fields.", responseField.Position));
                }
                else if (from == "body")
                {
                    if (!IsValidResponseBodyField(responseField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by body response field.", responseField.Position));
                    }
                    responseBodyFields.Add(new HttpBodyFieldInfo(responseField));
                }
                else if (from == "header")
                {
                    if (!IsValidSimpleField(responseField, serviceInfo))
                    {
                        AddValidationError(new ServiceDefinitionError("Type not supported by header response field.", responseField.Position));
                    }
                    responseHeaderFields.Add(new HttpHeaderFieldInfo(responseField));
                }
                else if (from == "normal" || from == null)
                {
                    responseNormalFields.Add(new HttpNormalFieldInfo(responseField));
                }
                else
                {
                    AddValidationError(new ServiceDefinitionError($"Unsupported 'from' parameter of 'http' attribute: '{from}'", responseField.Position));
                }
            }

            ResponseHeaderFields = responseHeaderFields;
            ValidResponses       = GetValidResponses(serviceInfo, statusCode, responseNormalFields, responseBodyFields).OrderBy(x => x.StatusCode).ToList();

            var duplicateStatusCode = ValidResponses.GroupBy(x => x.StatusCode).FirstOrDefault(x => x.Count() > 1);

            if (duplicateStatusCode != null)
            {
                AddValidationError(new ServiceDefinitionError($"Multiple handlers for status code {(int) duplicateStatusCode.Key}.", methodInfo.Position));
            }
        }
Пример #2
0
 internal HttpResponseInfo(HttpStatusCode statusCode, HttpBodyFieldInfo bodyField)
 {
     StatusCode = statusCode;
     BodyField  = bodyField;
 }
Пример #3
0
        internal HttpMethodInfo(ServiceMethodInfo methodInfo, ServiceInfo serviceInfo)
        {
            ServiceMethod = methodInfo;

            Method = HttpMethod.Post;
            Path   = $"/{methodInfo.Name}";
            HttpStatusCode?statusCode = null;

            foreach (var methodParameter in methodInfo.GetHttpParameters())
            {
                if (methodParameter.Name == "method")
                {
                    Method = GetHttpMethodFromParameter(methodParameter);
                }
                else if (methodParameter.Name == "path")
                {
                    if (methodParameter.Value.Length == 0 || methodParameter.Value[0] != '/')
                    {
                        throw new ServiceDefinitionException("'path' value must start with a slash.", methodParameter.Position);
                    }
                    Path = methodParameter.Value;
                }
                else if (methodParameter.Name == "code")
                {
                    statusCode = HttpAttributeUtility.ParseStatusCodeInteger(methodParameter);
                }
                else
                {
                    throw methodParameter.CreateInvalidHttpParameterException();
                }
            }

            var pathParameterNames = new HashSet <string>(GetPathParameterNames(Path));

            var requestPathFields              = new List <HttpPathFieldInfo>();
            var requestQueryFields             = new List <HttpQueryFieldInfo>();
            var requestNormalFields            = new List <HttpNormalFieldInfo>();
            HttpBodyFieldInfo requestBodyField = null;
            var requestHeaderFields            = new List <HttpHeaderFieldInfo>();

            foreach (var requestField in methodInfo.RequestFields)
            {
                string from = requestField.TryGetHttpAttribute()?.TryGetParameterValue("from");

                if (from == "path")
                {
                    if (!IsValidPathOrQueryField(requestField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Request field used in path must use a simple type.", requestField.Position);
                    }
                    var pathInfo = new HttpPathFieldInfo(requestField);
                    if (!pathParameterNames.Remove(pathInfo.Name))
                    {
                        throw new ServiceDefinitionException("Request field with [http(from: path)] has no placeholder in the method path.", requestField.Position);
                    }
                    requestPathFields.Add(pathInfo);
                }
                else if (from == "query")
                {
                    if (!IsValidPathOrQueryField(requestField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Request field used in query must use a simple type.", requestField.Position);
                    }
                    requestQueryFields.Add(new HttpQueryFieldInfo(requestField));
                }
                else if (from == "normal")
                {
                    if (Method == HttpMethod.Get || Method == HttpMethod.Delete)
                    {
                        throw new ServiceDefinitionException($"HTTP {Method} does not support normal fields.", requestField.Position);
                    }
                    requestNormalFields.Add(new HttpNormalFieldInfo(requestField));
                }
                else if (from == "body")
                {
                    if (!IsValidRequestBodyField(requestField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Request fields with [http(from: body)] must not use a primitive type.", requestField.Position);
                    }
                    if (requestBodyField != null)
                    {
                        throw new ServiceDefinitionException("Requests do not support multiple [http(from: body)] fields.", requestField.Position);
                    }
                    var bodyInfo = new HttpBodyFieldInfo(requestField);
                    if (bodyInfo.StatusCode != null)
                    {
                        throw new ServiceDefinitionException("Request fields do not support status codes.", requestField.Position);
                    }
                    requestBodyField = bodyInfo;
                }
                else if (from == "header")
                {
                    if (!IsValidHeaderField(requestField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Request fields with [http(from: header)] must use the string type.", requestField.Position);
                    }
                    requestHeaderFields.Add(new HttpHeaderFieldInfo(requestField));
                }
                else if (from != null)
                {
                    throw new ServiceDefinitionException($"Unsupported 'from' parameter of 'http' attribute: '{from}'", requestField.Position);
                }
                else if (pathParameterNames.Remove(requestField.Name))
                {
                    if (!IsValidPathOrQueryField(requestField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Request field used in path must use a simple type.", requestField.Position);
                    }
                    requestPathFields.Add(new HttpPathFieldInfo(requestField));
                }
                else if (Method == HttpMethod.Get || Method == HttpMethod.Delete)
                {
                    if (!IsValidPathOrQueryField(requestField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Request field used in query must use a simple type.", requestField.Position);
                    }
                    requestQueryFields.Add(new HttpQueryFieldInfo(requestField));
                }
                else
                {
                    requestNormalFields.Add(new HttpNormalFieldInfo(requestField));
                }
            }

            if (pathParameterNames.Count != 0)
            {
                throw new ServiceDefinitionException($"Unused path parameter '{pathParameterNames.First()}'.", methodInfo.Position);
            }
            if (requestBodyField != null && requestNormalFields.Count != 0)
            {
                throw new ServiceDefinitionException("A request cannot have a normal field and a body field.", requestBodyField.ServiceField.Position);
            }

            PathFields          = requestPathFields;
            QueryFields         = requestQueryFields;
            RequestNormalFields = requestNormalFields;
            RequestBodyField    = requestBodyField;
            RequestHeaderFields = requestHeaderFields;

            var responseNormalFields = new List <HttpNormalFieldInfo>();
            var responseBodyFields   = new List <HttpBodyFieldInfo>();
            var responseHeaderFields = new List <HttpHeaderFieldInfo>();

            foreach (var responseField in methodInfo.ResponseFields)
            {
                string from = responseField.TryGetHttpAttribute()?.TryGetParameterValue("from");

                if (from == "path" || from == "query")
                {
                    throw new ServiceDefinitionException($"Response fields do not support '[http(from: {from})]'.", responseField.Position);
                }
                else if (from == "body")
                {
                    if (!IsValidResponseBodyField(responseField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Response fields with [http(from: body)] must be a non-primitive type or a Boolean.", responseField.Position);
                    }
                    responseBodyFields.Add(new HttpBodyFieldInfo(responseField));
                }
                else if (from == "header")
                {
                    if (!IsValidHeaderField(responseField, serviceInfo))
                    {
                        throw new ServiceDefinitionException("Response fields with [http(from: header)] must use the string type.", responseField.Position);
                    }
                    responseHeaderFields.Add(new HttpHeaderFieldInfo(responseField));
                }
                else if (from == "normal" || from == null)
                {
                    responseNormalFields.Add(new HttpNormalFieldInfo(responseField));
                }
                else
                {
                    throw new ServiceDefinitionException($"Unsupported 'from' parameter of 'http' attribute: '{from}'", responseField.Position);
                }
            }

            ResponseHeaderFields = responseHeaderFields;
            ValidResponses       = GetValidResponses(serviceInfo, statusCode, responseNormalFields, responseBodyFields).OrderBy(x => x.StatusCode).ToList();

            var duplicateStatusCode = ValidResponses.GroupBy(x => x.StatusCode).FirstOrDefault(x => x.Count() > 1);

            if (duplicateStatusCode != null)
            {
                throw new ServiceDefinitionException($"Multiple handlers for status code {(int) duplicateStatusCode.Key}.", methodInfo.Position);
            }
        }