Swagger 導出API

Swagger 導出API

這算是在博客園的第一篇博客吧,以後發的應該也會同步到博客園上。前端

此前的博客地址: https://blog.mytyiluo.cnnode

Swagger簡介

Swagger是一個開源軟件框架,可幫助開發人員設計,構建,記錄和使用RESTful Web服務。ios

其中,Swagger能夠生成一個交互式的API控制檯,以便於快速測試API。git

從我的角度講,Swagger對於先後端分離的小團隊來講是很是有幫助的。尤爲是像咱們這種平時沒寫文檔習慣的人來講,Swagger能根據代碼自動生成文檔可謂是一大福音,不再用被人追着問這API究竟是怎麼用的。github

這裏,我將會具體說下最近我使用Swagger的一些心得和體會,團隊的開發環境以下:json

  • ASP.NET Core 2.1 (Visual Studio 2017 Community)
  • 微信小程序 (官方工具+Visual Studio Code)

生成Swagger API 文檔

對於ASP.NET Core來講,生成文檔這一步仍是相對容易的,且對代碼基本沒有侵入性。只需在Startup中配置一下便可,大體步驟基本以下:axios

添加NuGet包

這裏,我所使用的是Swashbuckle.AspNetCore,直接用VS的NuGet包管理器下載便可。小程序

NuGet-Swashbuckle.AspNetCore

而後在ConfigureServices中配置以下:後端

services.AddSwaggerGen(c =>
{
    // 定義文檔
    c.SwaggerDoc("v1", new Info { Title = "Qincai API", Version = "v1" });
});

並在Configure中啓用該Services:微信小程序

// 使用Swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "Qincai API v1");
});

隨後運行,打開瀏覽器host/swagger便可看到所生成的API文檔。

Swagger UI

若還有不清楚的,能夠參考微軟官方的文檔

完成到這裏,是否是發現你和圖中生成的樣子有點不太同樣,好比說,爲何沒有註釋,以及認證用的小鎖,那這裏咱們就須要進一步配置。

添加XML註釋

若是你們有在VS中寫C#經歷的話,確定會對XML註釋影響深入,經過簡單的///就能夠自動生成規範的註釋格式。那這裏,咱們的Swagger也正是利用了這些XML註釋來標記對應的API。

首先,咱們須要啓用VS中導出XML文檔的功能,在項目屬性中,生成 > 輸出,勾選XML文檔文件,並填寫對應的路徑,我所寫的是項目根目錄。

輸出XML文檔

而後再到以前的ConfigureServices中添加以下:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info { Title = "Qincai API", Version = "v1" });

    // file 是你在項目屬性中配置的相對路徑
    var filePath = System.IO.Path.Combine(AppContext.BaseDirectory, file);
    c.IncludeXmlComments(filePath);
});

從新生成,再運行,你能夠看到Swagger中就對API以及參數添加上了註釋。

添加認證功能

在實際開發中,咱們經常是須要給咱們的API添加上認證功能以免非法的訪問,所以咱們也就須要給Swagger中的API標識上是否須要認證,而且添加提供Token的功能,以方便在Swagger的控制檯中調試。

簡單來講,仍是在ConfigureServies中,配置以下:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info { Title = "Qincai API", Version = "v1" });

    var filePath = System.IO.Path.Combine(AppContext.BaseDirectory, file);
    c.IncludeXmlComments(filePath);

    // 定義認證方式
    c.AddSecurityDefinition("Bearer", new ApiKeyScheme
    {
        In = "header",
        Description = "請鍵入JWT Token,格式爲'Bearer '+你的Token。",
        Name = "Authorization",
        Type = "apiKey"
    });

    // 網上爲全局API添加認證參數的方法
    // c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> {
    //     { "Bearer", Enumerable.Empty<string>() },
    // });

    // 在過濾器中爲須要認證的API添加對應參數
    // 過濾器的定義見下文
    c.OperationFilter<AuthorizationHeaderOperationFilter>();
});

這裏值得說一下的是,網上廣泛都是全局添加認證參數,致使一些不須要認證的API也被打上了標識,這在Swagger 控制檯中影響倒不大,但在後續的導出API時就麻煩了,全部在這裏,我使用自定義過濾器的方式來只爲須要認證的API添加認證參數。

根據上文,咱們先定義一個AuthorizationHeaderOperationFilter類,它須要實現IOperationFilter接口,類定義以下:

/// <summary>
/// 判斷是否須要添加Authorize Header
/// </summary>
public class AuthorizationHeaderOperationFilter : IOperationFilter
{
    /// <summary>
    /// 爲須要認證的Operation添加認證參數
    /// </summary>
    /// <param name="operation">The Swashbuckle operation.</param>
    /// <param name="context">The Swashbuckle operation filter context.</param>
    public void Apply(Operation operation, OperationFilterContext context)
    {
        // 獲取對應方法的過濾器描述
        // 應該也就是所添加的Attribute
        var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
        // 判斷是否添加了AuthorizeFilter
        // 也就是[Authorize]
        var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
        // 判斷是否添加了IAllowAnonymousFilter
        // 也就是[AllowAnonymous]
        var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);

        // 僅當須要認證且不是AllowAnonymous的狀況下,添加認證參數
        if (isAuthorized && !allowAnonymous)
        {
            // 若該Operation不存在認證參數的話,
            // 這個Security將是null,而不是空的List
            if (operation.Security == null)
                operation.Security = new List<IDictionary<string, IEnumerable<string>>>();

            // 添加認證參數
            operation.Security.Add(new Dictionary<string, IEnumerable<string>>
            {
                { "Bearer", new string[] { } }
            });
        }
    }
}

從新生成後運行,應該就能夠看到須要認證的API都帶上了一把小鎖。

注意事項

雖然說配置並不算難,但仍是須要注意一些地方。

  1. 注意寫好XML註釋

    以前也說了,Swagger的註釋是根據XML文檔生成的,反過來講,若是你沒寫XML註釋,Swagger上也就是不會有註釋的。

    另外,在你啓用XML文檔輸出以後,VS也會很貼心的爲你把沒有寫XML註釋的地方都標爲Warning。╮(╯▽╰)╭,因此安心的把註釋都補一遍吧。

  2. 爲參數添加數據註解

    Swagger是支持部分數據註解的,好比[Required]之類的。

    結合[ApiController]自帶的模型驗證功能,豈不美哉。

  3. 將XML文檔複製到輸出目錄

    若你在發佈應用後發現XML不見了,那可能就是你沒有爲XML文檔文件配置複製到輸出目錄的屬性。

    打開資源管理器,右鍵對應的文件,咱們在屬性中能夠看到有複製到輸出目錄的屬性,將其設置爲始終複製就Ok。

    XML文檔屬性

以上就是我最近所用到的Swagger的一些功能。

導出微信小程序可用的API

在一開始也說了,使用Swagger的主要目的就是方便小團隊的溝通,但事實上,由於咱們前端的人少(你們都是CSS鬼才),致使咱們開發新API的速度每每比前端進度快,沒幾天前端那邊就須要更新一下API的庫(將小程序的CallBack封裝成Promise)。

所以,就有了根據Swagger自動生成Js可用的API文件的想法,其實想法的自己是來自於Abp項目的設計(真的很優秀),但出於一些方面的考慮,咱們姑且還沒采用Abp。

隨後,就是查找資料了,確實Swagger有這方面的支持,其中官方關於Js的庫是徹底動態的,但惋惜不適用於小程序。而後,就發現了第三方的swagger-js-codegen,可用於生成靜態的Js代碼,且提供了自定義模板的功能。網上也很多基於這個庫的其餘模板,好比說axios之類的,但沒有適用於微信小程序的,不過問題不大,模板是基於mustache的,動手擼就是了。

模板代碼有點長就不在這裏放出了,你們還請移步GitHub

這裏我就簡單說下大體思路,

模板自己是基於原來的nodejs模板改的,咱們所需作的就是將http請求部分的代碼改成使用wx.request,以下簡單的封裝便可:

/**
* HTTP Request
* @method
* @name {{&className}}#request
* @param {string} method - HTTP 請求方法
* @param {string} url - 開發者服務器接口地址
* @param {object} data - 請求的參數
* @param {object} headers - 設置請求的 header ,默認爲 application/json
*/
request(method, url, parameters, data, headers){
    return new Promise((resolve, reject) => {
        wx.request({
            url: url,
            data: data,
            header: headers,
            method: method,
            success: res => {
                if(res.statusCode >= 200 && res.statusCode <= 299) {
                    resolve(res.data)
                } else {
                    reject(res)
                }
            },
            fail: e => reject(e)
        })
    })
}

對應method的話,基本沒怎麼改,只根據微信小程序全部參數都是傳遞給data,作了點簡化。

對於認證部分,根據咱們本身的需求,換成了這樣的實現:

new Promise((resolve, reject) => {
    this.authenticate()
    .then(token => {
        headers['Authorization'] = 'Bearer ' + token;
        resolve(this.request('{{method}}', domain + path, parameters, data, headers))
    })
})

其中this.authenticate是由外部傳入的function,返回一個包含TokenPromise

導出後,在小程序中的使用就相似於:

import API from './api.js'

api = new API('http://localhost:5000')
api.setAuthenticate(function () {
    return new Promise((resolve, reject) => {
        // 你的認證邏輯
        resolve(token)
    })
})

而後,就能夠開心地調用各類方法了。

最後,再放一遍Demo的連接:https://github.com/yiluomyt/swagger-wxopen-codegen-template,發現有問題歡迎提Issue。

相關文章
相關標籤/搜索