OpenAPI - ianchen0119/Introduce-to-5GC GitHub Wiki

本文目標

  • 認識 OpenAPI
  • 更加深入的認識 SBI

進入正題

先前的文章有介紹到 SBI 是採用 HTTP/2 protocol 作為傳輸協定。 與 HTTP/1.1 相比,它支援 Multiplexing 以及 Header 的壓縮演算法 (HPACK)。並且,HTTP/2 使用 Binary 的方式傳輸,更將節省流量開銷。 不只如此,SBI 更採用了 RESTful API 的設計,讓 NF 與 NF 之間可以使用 HTTP Verb (POST, GET, PUT, DELETE) 溝通,提供了格式統一、簡潔易懂的 URL 操作。

OpenAPI

開放應用程式介面規格 (OAS,OpenAPI Specification) 是讓 Open API 得以被標準化的關鍵,OAS 原先名為 Swagger Specification,由一家名為 SmartBear 的軟體公司所發展,後由開放軟體社群及 Linux 合作贊助推動的 API 技術規格,開發出 OAS 國際標準。 OAS 定義了一套機器可讀的 API 規範,使其可以做更多元的應用。像是建立起互動式的 API 說明文件、產生靜態文件、產生客戶端/伺服器端程式碼架構等。由於 OAS 主要是以 YAML 或 JSON 格式來呈現,這樣的規格檔較為簡潔、輕便,讓我們在運用 OAS 的方式上,不受限於 top-down 或 bottom-up 的開發模式。 -- www.fisc.com.tw

3GPP 也採用了 OpenAPI 格式,讓開發者可以利用轉換工具產生專案的部分程式碼。 我們可以在 3GPP 的網站上找到相關文件與檔案,以 Nsmf_EventExposure 為例,其 OpenAPI 的 Yaml 檔可以在 TS 29.508 取得。

補充: 國外也有開發者針對 3GPP R15 與 R16 整理了 OpenAPI Specification Files,可以參考 5GC_APIs

產生程式碼

前面有提到 3GPP 提供了 OpenAPI Spec Files,有了這些檔案後就能夠搭配 OpenAPI generator 產生 API 相關的程式碼:

$ git clone https://github.com/jdegre/5GC_APIs.git
$ cd 5GC_APIs
$ docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i TS29522_5GLANParameterProvision.yaml -g go-gin-server -o /local/output

上面的範例使用 TS 29.522 5GLANParameterProvision 產生相關程式碼,執行完畢後可以使用以下命令檢查輸出的資料夾結構:

$ tree output

資料夾結構如下:

output
├── Dockerfile
├── api
│   └── openapi.yaml
├── go
│   ├── README.md
│   ├── api_class5_glan_parameters_provision_subscriptions.go
│   ├── api_individual5_glan_parameters_provision_subscription.go
│   ├── model_5_g_lan_parameters.go
│   ├── model_5_g_lan_parameters_patch.go
│   ├── model_5_g_lan_parameters_provision.go
│   ├── model_5_g_lan_parameters_provision_patch.go
│   ├── model_aaa_usage.go
│   ├── model_aaa_usage_any_of.go
│   ├── model_app_descriptor.go
│   ├── model_app_descriptor_rm.go
│   ├── model_invalid_param.go
│   ├── model_ipv6_addr.go
│   ├── model_pdu_session_type.go
│   ├── model_pdu_session_type_any_of.go
│   ├── model_problem_details.go
│   ├── model_snssai.go
│   └── routers.go
└── main.go

讓我們打開其中幾個檔案觀察輸出內容:

/*
 * 3gpp-5glan-pp
 *
 * API for 5G LAN Parameter Provision.   © 2022, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC).   All rights reserved. 
 *
 * API version: 1.1.0-alpha.3
 * Generated by: OpenAPI Generator (https://openapi-generator.tech)
 */

package openapi

// Model5GLanParameters - Represents 5G LAN service related parameters that need to be provisioned.
type Model5GLanParameters struct {

	// string containing a local identifier followed by \"@\" and a domain identifier. Both the local identifier and the domain identifier shall be encoded as strings that do not contain any \"@\" characters. See Clauses 4.6.2 and 4.6.3 of 3GPP TS 23.682 for more information.
	ExterGroupId string `json:"exterGroupId"`

	// Contains the list of 5G VN Group members, each member is identified by GPSI. Any string value can be used as a key of the map. 
	Gpsis map[string]string `json:"gpsis"`

	// String representing a Data Network as defined in clause 9A of 3GPP TS 23.003; it shall contain either a DNN Network Identifier, or a full DNN with both the Network Identifier and Operator Identifier, as specified in 3GPP TS 23.003 clause 9.1.1 and 9.1.2. It shall be coded as string in which the labels are separated by dots (e.g. \"Label1.Label2.Label3\").
	Dnn string `json:"dnn"`

	// String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
	AaaIpv4Addr string `json:"aaaIpv4Addr,omitempty"`

	AaaIpv6Addr Ipv6Addr `json:"aaaIpv6Addr,omitempty"`

	AaaUsgs []AaaUsage `json:"aaaUsgs,omitempty"`

	// String uniquely identifying MTC provider information.
	MtcProviderId string `json:"mtcProviderId,omitempty"`

	Snssai Snssai `json:"snssai"`

	SessionType PduSessionType `json:"sessionType"`

	// Further allowed PDU Session types.
	SessionTypes []PduSessionType `json:"sessionTypes,omitempty"`

	// Describes the operation systems and the corresponding applications for each operation systems. The key of map is osId.
	AppDesps map[string]AppDescriptor `json:"appDesps"`
}
/*
 * 3gpp-5glan-pp
 *
 * API for 5G LAN Parameter Provision.   © 2022, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC).   All rights reserved. 
 *
 * API version: 1.1.0-alpha.3
 * Generated by: OpenAPI Generator (https://openapi-generator.tech)
 */

package openapi

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Route is the information for every URI.
type Route struct {
	// Name is the name of this Route.
	Name        string
	// Method is the string for the HTTP method. ex) GET, POST etc..
	Method      string
	// Pattern is the pattern of the URI.
	Pattern     string
	// HandlerFunc is the handler function of this route.
	HandlerFunc gin.HandlerFunc
}

// Routes is the list of the generated Route.
type Routes []Route

// NewRouter returns a new router.
func NewRouter() *gin.Engine {
	router := gin.Default()
	for _, route := range routes {
		switch route.Method {
		case http.MethodGet:
			router.GET(route.Pattern, route.HandlerFunc)
		case http.MethodPost:
			router.POST(route.Pattern, route.HandlerFunc)
		case http.MethodPut:
			router.PUT(route.Pattern, route.HandlerFunc)
		case http.MethodPatch:
			router.PATCH(route.Pattern, route.HandlerFunc)
		case http.MethodDelete:
			router.DELETE(route.Pattern, route.HandlerFunc)
		}
	}

	return router
}

// Index is the index handler.
func Index(c *gin.Context) {
	c.String(http.StatusOK, "Hello World!")
}

var routes = Routes{
	{
		"Index",
		http.MethodGet,
		"/3gpp-5glan-pp/v1/",
		Index,
	},

	{
		"AfIdSubscriptionsGet",
		http.MethodGet,
		"/3gpp-5glan-pp/v1/:afId/subscriptions",
		AfIdSubscriptionsGet,
	},

	{
		"AfIdSubscriptionsPost",
		http.MethodPost,
		"/3gpp-5glan-pp/v1/:afId/subscriptions",
		AfIdSubscriptionsPost,
	},

	{
		"AfIdSubscriptionsSubscriptionIdDelete",
		http.MethodDelete,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdDelete,
	},

	{
		"AfIdSubscriptionsSubscriptionIdGet",
		http.MethodGet,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdGet,
	},

	{
		"AfIdSubscriptionsSubscriptionIdPatch",
		http.MethodPatch,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdPatch,
	},

	{
		"AfIdSubscriptionsSubscriptionIdPut",
		http.MethodPut,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdPut,
	},
}
  • 觀察輸出的檔案不難發現:Code generator 已經把這個 API 會使用到的 struct、router、handler 的骨幹都產生出來了。
  • 有了這些基本的程式碼能夠加快每一個 API feature 的開發速度(只需要再去翻閱相關的規格書並將細節實作出來,不需要浪費時間去定義相關的成員結構以及 API 路由)。