在 Swift 中管理多个 RESTful API 端点的简单方法
什么是 APIRouter 📟
APIRouter 提供了一种在 Swift 中管理多个 RESTful API 端点的简单方法。 它提供了一个简单的界面来管理多个端点,并允许开发人员以单一、统一的方式与它们进行交互。 它还为开发人员提供了一种创建自定义终结点 DSL(域特定语言)和管理每个终结点自己的设置的方法。 此外,它还提供了一种跟踪每个终结点的状态并轻松检测所做的任何更改或更新的方法。
与 Swift evolution 的正则表达式生成器 DSL 类似,URL 字符串文字和更强大的模式结果生成器有助于使 Swift URL 字符串处理快速、简单且没有错误。最终,使用 APIRouter,更改很容易检测到并且对维护很有用。
🤔 在这里提出你想知道的问题。在这里分享想法。 💡
安装 📦
-
使用 Swift 包管理器
import PackageDescription let package = Package( name: "SomeApp", dependencies: [ .Package(url: "https://github.com/devyhan/APIRouter", majorVersion: "<LATEST_RELEASES_VERSION>"), ] )
Configure APIRouter 📝
Implement APIs Namespace
- To implement APIs namespace we create a new type that will house the domain and behavior of the APIs by conforming to .
RouterProtocol
import APIRouter
public enum APIs: RouterProtocol {
...
}
HttpHeader declaration
- Using to declaration.
HeaderBuilder
httpHeader
Request {
...
Header {
Field("HEADERVALUE", forKey: "HEADERKEY")
Field("HEADERVALUE1", forKey: "HEADERKEY1")
Field("HEADERVALUE2", forKey: "HEADERKEY2")
...
}
...
}
- Using to declaration.
Dictionary
httpHeader
Request {
...
Header([
"HEADERKEY": "HEADERVALUE",
"HEADERKEY1": "HEADERVALUE1",
"HEADERKEY2": "HEADERVALUE2",
...
])
...
}
HttpBody declaration
- Using to declaration.
HeaderBuilder
httpHeader
Request {
...
Body {
Param("VALUE", forKey: "KEY")
Param("VALUE1", forKey: "KEY1")
Param("VALUE2", forKey: "KEY2")
...
}
...
}
- Using to declaration.
Dictionary
httpHeader
Request {
...
Body([
"KEY": "VALUE",
"KEY1": "VALUE1",
"KEY2": "VALUE2",
...
])
...
}
HttpMethod declaration
- Using to declaration.
Method(_ method:)
httpMethod
Request {
...
Method(.get)
...
}
URL declaration
- Using to declaration.
URL(_ url:)
URL
Request {
...
URL("https://www.baseurl.com/comments?postId=1")
...
}
- Using to declaration and declaration.
URLBuilder
URL
URLComponents
Request {
...
URL {
Scheme(.https)
Host("www.baseurl.com")
Path("comments")
Query("postId", value: "1")
}
...
}
// https://www.baseurl.com/comments?postId=1
- Using for override.
BaseURL(_ url:)
URL
Request {
BaseURL("https://www.baseurl.com")
URL {
Path("comments")
Query("postId", value: "1")
}
}
// https://www.baseurl.com/comments?postId=1
Router {
BaseURL("https://www.baseurl.com")
Request {
URL {
Scheme(.https)
Host("www.overrideurl.com")
Path("comments")
Query("postId", value: "1")
}
}
}
// https://www.overrideurl.com/comments?postId=1
How to configure and use APIRouter in a real project?
- Just create APIRouter.swift in your project! Happy hacking! 😁
import APIRouter
enum APIs: RouterProtocol {
// DOC: https://docs.github.com/ko/rest/repos/repos?apiVersion=2022-11-28#list-organization-repositories
case listOrganizationRepositories(organizationName: String)
// DOC: https://docs.github.com/ko/rest/repos/repos?apiVersion=2022-11-28#create-an-organization-repository
case createAnOrganizationRepository(organizationName: String, repositoryInfo: RepositoryInfo)
// DOC: https://docs.github.com/ko/rest/search?apiVersion=2022-11-28#search-repositories
case searchRepositories(query: String)
struct RepositoryInfo {
let name: String
let description: String
let homePage: String
let `private`: Bool
let hasIssues: Bool
let hasProjects: Bool
let hasWiki: Bool
}
var router: Router? {
Router {
BaseURL("http://api.github.com")
switch self {
case let .listOrganizationRepositories(organizationName):
Request {
Method(.post)
Header {
Field("application/vnd.github+json", forKey: "Accept")
Field("Bearer <YOUR-TOKEN>", forKey: "Authorization")
Field("2022-11-28", forKey: "X-GitHub-Api-Version")
}
URL {
Path("orgs/\(organizationName)/repos")
}
}
case let .createAnOrganizationRepository(organizationName, repositoryInfo):
Request {
Method(.post)
Header {
Field("application/vnd.github+json", forKey: "Accept")
Field("Bearer <YOUR-TOKEN>", forKey: "Authorization")
Field("2022-11-28", forKey: "X-GitHub-Api-Version")
}
URL {
Path("orgs/\(organizationName)/repos")
}
Body {
Param(repositoryInfo.name, forKey: "name")
Param(repositoryInfo.description, forKey: "description")
Param(repositoryInfo.homePage, forKey: "homepage")
Param(repositoryInfo.private, forKey: "private")
Param(repositoryInfo.hasIssues, forKey: "has_issues")
Param(repositoryInfo.hasProjects, forKey: "has_projects")
Param(repositoryInfo.hasWiki, forKey: "has_wiki")
}
}
case let .searchRepositories(query):
Request {
Method(.get)
Header {
Field("application/vnd.github+json", forKey: "Accept")
Field("Bearer <YOUR-TOKEN>", forKey: "Authorization")
Field("2022-11-28", forKey: "X-GitHub-Api-Version")
}
URL {
Path("search/repositories")
Query("q", value: query)
}
}
}
}
}
}
// http://api.github.com/orgs/organization/repos
let listOrganizationRepositoriesUrl = APIs.listOrganizationRepositories(organizationName: "organization").router?.urlRequest?.url
// http://api.github.com/search/repositories?q=apirouter
let searchRepositoriesUrl = APIs.searchRepositories(query: "apirouter").router?.urlRequest?.url
let repositoryInfo: APIs.RepositoryInfo = .init(name: "Hello-World", description: "This is your first repository", homePage: "https://github.com", private: false, hasIssues: true, hasProjects: true, hasWiki: false)
let request = APIs.createAnOrganizationRepository(organizationName: "SomeOrganization", repositoryInfo: repositoryInfo).router?.urlRequest
URLSession.shared.dataTask(with: request) { data, response, error in
...