/// <summary> /// Validates the Swagger model and adds any violations to the collection. /// </summary> /// <param name="swagger">The model to validate. Must not be null. </param> /// <param name="result">The collection that will contain any violations. Must not be null. </param> public static void Validate(Swagger swagger, ViolationCollection result) { if (null == swagger) throw new System.ArgumentNullException("swagger"); if (null == result) throw new System.ArgumentNullException("result"); // Swagger if (string.Compare(swagger.Version, "2.0", true) != 0) result.Add(new Violation() { Code = "Swagger", ViolationLevel = ViolationLevel.Error, Context = "Version", Description = @"Specifies the Swagger Specification version being used. It can be used by the Swagger UI and other clients to interpret the API listing. The value MUST be ""2.0"")" }); // Host if (swagger.Host == null || !(swagger.Host.Length > 0)) result.Add(new Violation() { Code = "Host", ViolationLevel = ViolationLevel.Informational, Context = "Host", Description = @"The host (name or ip) serving the API. This MUST be the host only and does not include the scheme nor sub-paths. It MAY include a port. If the host is not included, the host serving the documentation is to be used (including the port). The host does not support path templating." }); // Basepath if (swagger.BasePath == null || !swagger.BasePath.StartsWith("/")) result.Add(new Violation() { Code = "BasePath", ViolationLevel = ViolationLevel.Informational, Context = "BasePath", Description = @"Specifies the Swagger Specification version being used. It can be used by the Swagger UI and other clients to interpret the API listing. The value MUST be ""2.0"")" }); // Schemes var schemesValid = (swagger.Schemes != null); if (schemesValid) { schemesValid = (swagger.Schemes.Count() != 0); if (schemesValid) { var allowed = new string[4] { "http", "https", "ws", "wss" }; foreach (var scheme in swagger.Schemes) { var match = allowed.FirstOrDefault(f => string.Compare(f, scheme, false) == 0); if (match == null) { schemesValid = false; break; } } } } if (!schemesValid) { result.Add(new Violation() { Code = "Schemes", ViolationLevel = ViolationLevel.Informational, Context = "Schemes", Description = @"The transfer protocol of the API. Values MUST be from the list: ""http"", ""https"", ""ws"", ""wss"". If the schemes is not included, the default scheme to be used is the one used to access the specification." }); } // ExternalDocs ValidateExternalDocs(swagger.ExternalDocs, "ExternalDocs", result); // Info var infoValid = (swagger.Info != null); if (!infoValid) result.Add(new Violation() { Code = "Info", ViolationLevel = ViolationLevel.Error, Context = "Info", Description = @"Required Provides the version of the application API (not to be confused by the specification version)." }); if (infoValid) { ValidateRequiredProperty(swagger.Info.Title, "Info.Title", ViolationLevel.Error, @"Required. The title of the application.", result); ValidateRequiredProperty(swagger.Info.Version, "Info.Version", ViolationLevel.Error, @"Required. The title of the application.", result); } // Contact if (swagger.Contact != null) { ValidateNotRequiredUrl(swagger.Contact.Url, "Contact.Url", ViolationLevel.Error, @"The URL pointing to the contact information. MUST be in the format of a URL.", result); } // License if (swagger.License != null) { ValidateRequiredProperty(swagger.License.Name, "License.Name", ViolationLevel.Error, @"Required. The license name used for the API.", result); ValidateNotRequiredUrl(swagger.License.Url, "License.Url", ViolationLevel.Error, @"A URL to the license used for the API. MUST be in the format of a URL.", result); } // Tags if (swagger.Tags != null) { // We need to validate each of the Tags foreach (var tag in swagger.Tags) { var index = swagger.Tags.ToList().IndexOf(tag); ValidateTag(tag, string.Format("Tags[{0}]", index), @"Required. The name of the tag.", result); // See if there is another tag by this name that is not us. var match = swagger.Tags.FirstOrDefault(f => string.Compare(f.Name, tag.Name, true) == 0 && f != tag && swagger.Tags.ToList().IndexOf(f) > index); if (match == null) continue; var context = string.Format("Tags[{0}].Name", swagger.Tags.ToList().IndexOf(match)); result.Add(new Violation() { Code = context, ViolationLevel = ViolationLevel.Error, Context = context, Description = @"Required. The name of the tag. Must be unique. " }); } } }
public void SwaggerSanityNotSafe() { Swagger = new Moksy.Common.Swagger20.Swagger(false); Assert.AreEqual("2.0", Swagger.Version); Assert.IsNull(Swagger.Host); Assert.IsNull(Swagger.BasePath); Assert.IsNull(Swagger.Schemes); Assert.IsNull(Swagger.Consumes); Assert.IsNull(Swagger.Produces); Assert.IsNull(Swagger.ExternalDocs); Assert.IsNotNull(Swagger.Info); Assert.IsNotNull(Swagger.Info.Title); Assert.IsNotNull(Swagger.Info.Version); Assert.IsNull(Swagger.Info.Description); Assert.IsNull(Swagger.Info.TermsOfService); Assert.IsNull(Swagger.Contact); Assert.IsNull(Swagger.License); Assert.IsNull(Swagger.Tags); var result = SwaggerValidator.Validate(Swagger); var errors = result.Where(f => f.ViolationLevel == ViolationLevel.Error); Assert.AreEqual(0, errors.Count()); }
/// <summary> /// Validates the Swagger model and returns any violations. /// </summary> /// <param name="swagger">The model. Must not be null. </param> /// <returns>A collection of zero or more violations. </returns> public static ViolationCollection Validate(Swagger swagger) { ViolationCollection result = new ViolationCollection(); Validate(swagger, result); return result; }
public void Setup() { Swagger = new Moksy.Common.Swagger20.Swagger(); }