Когда вы представляете свой сервис как веб-API, возникает вопрос о том, как информировать пользователя о его возможностях, синтаксисе его запросов и т. д. Обычно вам приходится создавать отдельные веб-страницы, на которых вы освещаете эти темы.
Но не лучше ли было бы, если бы ваш веб-API сам предоставлял доступ к своей документации? Если вы откроете страницу какого-то серьезного проекта на GitHub , вы увидите хорошо оформленный Readme.md .
Этот Уценка -Документ описывает назначение кода, хранящегося в репозитории, и часто содержит ссылки на другие документы.
GitHub автоматически преобразует Markdown в HTML и показывает результат в удобной для чтения форме.
Это делает файлы Markdown удобным способом хранения документации о вашем проекте.
Прежде всего, этот формат предоставляет достаточно богатые возможности по форматированию текста.
Кроме того, эти файлы хранятся в вашей системе контроля версий (VCS) вместе с вашим кодом.
Это приравнивает такие документы к самим файлам кода (первосортным гражданам).
Вы рассматриваете их как часть кода и меняете их при внесении изменений в код. По крайней мере, так должно быть в теории.
Теперь у вас есть вся документация в вашем репозитории.
Если ваш репозиторий открыт, то все отлично.
Пользователи вашего API смогут увидеть там документацию.
Но я работаю в компании, которая предоставляет некоторые веб-API внешним клиентам.
Эти клиенты не имеют доступа к нашим репозиториям.
Как мы можем предоставить им документацию о наших услугах? Вы можете создать отдельный сайт с документацией.
Но тогда у нас будет 2 места хранения информации о продукте: в файлах Markdown и на этом сайте.
Вы, конечно, можете автоматизировать процесс создания сайта документации, сгенерировав его из документов Markdown. Или вы можете создать отдельный документ (например, PDF), включающий содержимое всех этих файлов.
В этом подходе нет ничего плохого.
Но я думаю, что мы можем сделать еще один шаг в этом направлении.
Почему мы отделяем документацию от самого API? Можно ли их поставить вместе? Например, наш веб-API доступен по адресу www.something.com/api/data , а его документация доступна по адресу www.something.com/api/help.md Насколько сложно реализовать этот подход в веб-API ASP.NET? Давайте посмотрим.
Начнем с простого веб-API, основанного на OWIN. Вот мой Запускать файл:
Давайте добавим в проект несколько файлов Markdown:[assembly: OwinStartup(typeof(OwinMarkdown.Startup))] namespace OwinMarkdown { public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); config.Formatters.Clear(); config.Formatters.Add( new JsonMediaTypeFormatter { SerializerSettings = GetJsonSerializerSettings() }); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {id = RouteParameter.Optional} ); app.UseWebApi(config); } private static JsonSerializerSettings GetJsonSerializerSettings() { var settings = new JsonSerializerSettings(); settings.Converters.Add(new StringEnumConverter { CamelCaseText = false }); settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); return settings; } } }
Несколько слов следует сказать о добавленных файлах.
Прежде всего, у нас может быть сложная структура подпапок, в которой хранятся различные части нашей документации.
Кроме того, у нас есть и другие файлы, а не только Markdown. Например, наша документация может содержать изображения, на которые будут ссылаться документы Markdown. Поэтому наше решение по предоставлению документации через Web API должно поддерживать как структуру папок, так и дополнительные файлы.
Начнем изменения из файла Веб.
конфигурация .
Он требует некоторых модификаций.
Дело в том, что службы Internet Information Services (IIS) могут доставлять статические файлы пользователю самому, без участия нашего приложения.
Например, если пользователь запрашивает мойхост/помощь/root.md , IIS поймет, что на диске есть такой файл и сам его вернет. Это означает, что IIS не передаст запрос нашему приложению.
Но это не то, чего мы хотим.
Нам не нужно возвращать необработанный файл Markdown, мы хотим сначала преобразовать его в HTML. Вот почему нам необходимо внести изменения в Веб.
конфигурация .
Нам нужно указать IIS передавать все запросы нашему приложению, не пытаясь выполнить их самостоятельно.
Это можно сделать, создав раздел system.webServer : <system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb" />
</handlers>
</system.webServer>
Теперь IIS не будет обрабатывать статические файлы.
Но нам все равно придется их предоставить (например, для картинок в нашей документации).
Поэтому мы будем использовать пакет NuGet. Microsoft.Owin.StaticFiles .
Итак, если мы хотим, чтобы наша документация была доступна по адресу /api/док , мы должны настроить этот пакет следующим образом: [assembly: OwinStartup(typeof(OwinMarkdown.Startup))]
namespace OwinMarkdown
{
public class Startup
{
private static readonly string HelpUrlPart = "/api/doc";
public void Configuration(IAppBuilder app)
{
var basePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
app.UseStaticFiles(new StaticFileOptions
{
RequestPath = new PathString(HelpUrlPart),
FileSystem = new PhysicalFileSystem(Path.Combine(basePath, "Help"))
});
HttpConfiguration config = new HttpConfiguration();
config.Formatters.Clear();
config.Formatters.Add(
new JsonMediaTypeFormatter
{
SerializerSettings = GetJsonSerializerSettings()
});
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional}
);
app.UseWebApi(config);
}
private static JsonSerializerSettings GetJsonSerializerSettings()
{
var settings = new JsonSerializerSettings();
settings.Converters.Add(new StringEnumConverter { CamelCaseText = false });
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
return settings;
}
}
}
Теперь возвращаем статические файлы из папки Помощь наше приложение на /api/док .
Но нам все равно нужно каким-то образом преобразовать документы Markdown в HTML перед их возвратом.
Для этой цели мы напишем собственное промежуточное программное обеспечение OWIN. Это промежуточное ПО будет использовать пакет NuGet. Маркдиг .
[assembly: OwinStartup(typeof(OwinMarkdown.Startup))]
namespace OwinMarkdown
{
public class Startup
{
private static readonly string HelpUrlPart = "/api/doc";
public void Configuration(IAppBuilder app)
{
var pipeline = new MarkdownPipelineBuilder().
UseAdvancedExtensions().
Build(); app.Use(async (context, next) => { var markDownFile = GetMarkdownFile(context.Request.Path.ToString()); if (markDownFile == null) { await next(); return; } using (var reader = markDownFile.OpenText()) { context.Response.ContentType = @"text/html"; var fileContent = reader.ReadToEnd(); fileContent = Markdown.ToHtml(fileContent, pipeline); // Send our modified content to the response body. await context.Response.WriteAsync(fileContent); } }); var basePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; app.UseStaticFiles(new StaticFileOptions { RequestPath = new PathString(HelpUrlPart), FileSystem = new PhysicalFileSystem(Path.Combine(basePath, "Help")) }); HttpConfiguration config = new HttpConfiguration(); config.Formatters.Clear(); config.Formatters.Add( new JsonMediaTypeFormatter { SerializerSettings = GetJsonSerializerSettings() }); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {id = RouteParameter.Optional} ); app.UseWebApi(config); } private static JsonSerializerSettings GetJsonSerializerSettings() { var settings = new JsonSerializerSettings(); settings.Converters.Add(new StringEnumConverter { CamelCaseText = false }); settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); return settings; } private static FileInfo GetMarkdownFile(string path) { if (Path.GetExtension(path) != ".
md")
return null;
var basePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
var helpPath = Path.Combine(basePath, "Help");
var helpPosition = path.IndexOf(HelpUrlPart + "/", StringComparison.OrdinalIgnoreCase);
if (helpPosition < 0)
return null;
var markDownPathPart = path.Substring(helpPosition + HelpUrlPart.Length + 1);
var markDownFilePath = Path.Combine(helpPath, markDownPathPart);
if (!File.Exists(markDownFilePath))
return null;
return new FileInfo(markDownFilePath);
}
}
}
Давайте посмотрим, как работает это промежуточное программное обеспечение.
Прежде всего, он проверяет, был ли запрос файлом Markdown или чем-то другим.
Это то, что делает функция ПолучитьMarkdownFile .
Он пытается найти файл Markdown, соответствующий запросу, и возвращает его.
Информация о файле , если файл был найден, или null, если он не был найден.
Реализация не самая лучшая, но она служит для проверки идеи.
Его можно заменить любой другой реализацией.
Если файл не найден, промежуточное программное обеспечение передает запрос дальше, используя жду следующего() .
Но если файл найден, его содержимое считывается, преобразуется в HTML и возвращается в ответе.
Теперь у нас есть документация, которую пользователь может увидеть в нескольких местах.
Его можно посмотреть в репозитории VCS (например, GitHub).
Он также доступен непосредственно через наш веб-API. Кроме того, документация — это часть нашего кода, который мы храним под VCS. Я считаю, что это очень хороший результат. Однако следует обсудить и его недостатки.
Прежде всего, такая система хороша, если ваш продукт уже стабилен.
Но на ранних этапах разработки не всегда понятно, как должно выглядеть ваше API, какой формат должны иметь запросы и ответы и т. д. На этом этапе документация должна быть открыта для комментариев.
Поэтому вам понадобится какой-то инструмент, позволяющий комментировать содержимое файлов Markdown. В GitHub есть система проблем, где вы можете оставлять комментарии к коду.
Поскольку документация теперь является частью кода, Issues можно использовать для обсуждения ее содержимого во время разработки.
Но лично я считаю, что это не лучшее решение.
Гораздо удобнее было бы писать комментарии прямо в документе, как это возможно в Слияние .
Короче говоря, я считаю, что необходим хороший инструмент для обсуждения документов Markdown на ранних стадиях разработки.
Мои коллеги из компании Подтверди это указал еще на несколько недостатков описанного решения, о которых следует упомянуть.
Доставка документации вместе с API может негативно повлиять на производительность вашего сервиса, поскольку теперь один Пул потоков будет использоваться как для обслуживания запросов к самому веб-API, так и для запросов к документации.
Кроме того, добавление точки доступа в документацию расширяет поверхность атаки для вашего сервиса.
Вам необходимо решить, предоставляете ли вы доступ к документации только авторизованным пользователям или кому угодно.
В последнем случае открывается возможность DoS-атаки на точку доступа к документации.
А поскольку документацию предоставляет тот же сервис, что и Web API, это тоже может негативно сказаться на работе самого API. На этом статья завершается.
Надеюсь, представленная в нем идея окажется полезной хотя бы как отправная точка для дальнейших исследований.
Теги: #web api #документация #.
NET #ASP #ASP #C++
-
Yahoo! Закрывает Сервис Music Unlimited
19 Oct, 24 -
8 Способов Избежать Паники Во Время Кризиса
19 Oct, 24