iOS 检查接口参数是否和文档一致,防止疏忽导致书写错误的一些思考

在iOS开发过程中,我们在编码Server接口的时候,不可避免的要硬编码一些接口名、参数key等文档中定义的内容。而怎么防止由于人的原因,编码意识模糊一时大意导致这些硬编码出错的问题?

暂时想到了两种方式,一种静态,一种动态。

1.静态处理的方式,需要开发人员在编码过程中,在接口代码编写时需遵循某种指定的格式,或添加某些指定的注释或标记。然后通过shell脚本,在Xcode的run script中,或CI系统中执行,检查相关文件携带指定标记的代码,看是否和Server文档标准中一致。这样可以一次性检查全部的接口。

2.动态处理的方式,需要修改网络层代码,在请求前或请求成功后,得到Request或Response,再根据本地导入的xml、Plist格式的Server文档标准文件,通过比对文档中的数据与请求数据是否一致,来得出结论。这个只能项目运行起来,用了哪个接口才能检查哪个。

依赖:

这两种方案,实际上都非常依赖一份Server提供的指定格式的标准文档,但Server本身就在维护一份接口文档,现在又要出一份xml或者Plist格式的文档,增加了他们的工作量。

解决方案:

初步想到的是,自行研发一套接口文档编写系统,通过规范编写方法,在某些位置的接口文档需要遵循某些编写格式,提交到数据库后,再通过专门的接口或功能将这些内容导出为json或xml或Plist文件即可。

动态处理的方案,写了一个简单的demo,可以实现在接口书写错误的情况下,报错提示程序员哪里错误。如下:

这个是接口规范文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>/mall/login</key>
	<dict>
		<key>POST</key>
		<dict>
			<key>header</key>
			<false/>
			<key>parameters</key>
			<dict>
				<key>loginId</key>
				<true/>
				<key>loginMethod</key>
				<true/>
				<key>password</key>
				<true/>
			</dict>
		</dict>
		<key>GET</key>
		<dict>
			<key>header</key>
			<false/>
			<key>parameters</key>
			<dict>
				<key>refreshToken</key>
				<true/>
			</dict>
		</dict>
	</dict>
</dict>
</plist>

这个是校验逻辑,我是写在了接口返回的时候,代码没有好好处理,只是提供个思路,请勿直接使用:

    private func validate(response: DataResponse<Any>) {
        guard let request = response.request else {
            return
        }
        let path = Bundle.main.path(forResource: "NetworkDocument", ofType: "xml") ?? ""
        if let dict = NSDictionary(contentsOfFile: path) as? [String: [String: [String: Any]]] {
            let apiKeys = dict.keys
            var matchedKey = ""
            let apiMatch = apiKeys.contains(where: { (key) -> Bool in
                if request.url?.absoluteString.contains(key) ?? false {
                    matchedKey = key
                    return true
                } else {
                    return false
                }
            })
            if apiMatch {
                if let subDict = dict[matchedKey] {
                    if subDict.keys.contains(request.httpMethod ?? "") {
                        let method = request.httpMethod ?? ""
                        if let finalDict = subDict[request.httpMethod ?? ""] {
                            let header = finalDict["header"] as? Bool ?? true
                            let auth = request.value(forHTTPHeaderField: "Authorization") ?? ""
                            if header == true {
                                if auth.isEmpty {
                                    fatalError("header validation failed in <\(matchedKey)> API")
                                }
                            }
                            if let parameters = finalDict["parameters"] as? [String: Bool] {
                                for (key, value) in parameters {
                                    if value == true {
                                        if method == "GET" {
                                            if !(request.url?.absoluteString.contains(key) ?? false) {
                                                fatalError("parameters validation failed in <\(matchedKey)> API, missing key <\(key)>")
                                            }
                                        } else {
                                            if let body = request.httpBody {
                                                let bodyDict = try? JSONSerialization.jsonObject(with: body, options: .allowFragments) as? Dictionary<String, Any> ?? [:]
                                                if !(bodyDict?.keys.contains(key) ?? false) {
                                                    fatalError("parameters validation failed in <\(matchedKey)> API, missing key <\(key)>")
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        fatalError("method validation failed in <\(matchedKey)> API")
                    }
                }
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/pilgrim1385/article/details/88867605
今日推荐