internal HttpBodyFieldInfo(ServiceFieldInfo fieldInfo) { ServiceField = fieldInfo; foreach (var parameter in fieldInfo.GetHttpParameters()) { if (parameter.Name == "code") { StatusCode = HttpAttributeUtility.ParseStatusCodeInteger(parameter); } else if (parameter.Name != "from") { throw parameter.CreateInvalidHttpParameterException(); } } }
internal HttpErrorInfo(ServiceErrorInfo errorInfo) { ServiceError = errorInfo; StatusCode = HttpStatusCode.InternalServerError; foreach (var parameter in errorInfo.GetHttpParameters()) { if (parameter.Name == "code") { StatusCode = HttpAttributeUtility.ParseStatusCodeInteger(parameter); } else { throw parameter.CreateInvalidHttpParameterException(); } } }
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); } }