{"id":25863000,"url":"https://github.com/rfui/rfapi","last_synced_at":"2026-05-02T05:31:33.224Z","repository":{"id":62451878,"uuid":"127090218","full_name":"RFUI/RFAPI","owner":"RFUI","description":"RFAPI is a network request library specially designed for API requests. It is a URL session wrapper base on AFNetworking.","archived":false,"fork":false,"pushed_at":"2021-09-13T12:27:29.000Z","size":433,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2025-05-31T16:29:26.883Z","etag":null,"topics":["afnetworking","api","http-client","http-requests","ios","macos","tvos","urlrequest","urlsession"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RFUI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-28T05:50:36.000Z","updated_at":"2021-09-13T11:28:46.000Z","dependencies_parsed_at":"2022-11-01T23:45:27.728Z","dependency_job_id":null,"html_url":"https://github.com/RFUI/RFAPI","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RFUI%2FRFAPI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RFUI%2FRFAPI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RFUI%2FRFAPI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RFUI%2FRFAPI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RFUI","download_url":"https://codeload.github.com/RFUI/RFAPI/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RFUI%2FRFAPI/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258521887,"owners_count":22714422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["afnetworking","api","http-client","http-requests","ios","macos","tvos","urlrequest","urlsession"],"created_at":"2025-03-01T23:58:08.253Z","updated_at":"2026-05-02T05:31:33.179Z","avatar_url":"https://github.com/RFUI.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RFAPI\n\n\u003c!-- markdownlint-disable MD033 inline html --\u003e\n\n[![Build Status](https://img.shields.io/travis/RFUI/RFAPI.svg?style=flat-square\u0026colorA=333333\u0026colorB=6600cc)](https://travis-ci.com/RFUI/RFAPI)\n[![Codecov](https://img.shields.io/codecov/c/github/RFUI/RFAPI.svg?style=flat-square\u0026colorA=333333\u0026colorB=6600cc)](https://codecov.io/gh/RFUI/RFAPI)\n[![CocoaPods](https://img.shields.io/cocoapods/v/RFAPI.svg?style=flat-square\u0026colorA=333333\u0026colorB=6600cc)](https://cocoapods.org/pods/RFAPI)\n\n\u003cbase href=\"//github.com/RFUI/RFAPI/blob/develop/\" /\u003e\n\n\u003csmall\u003e*English* [简体中文 :cn:](README.zh-hans.md)\u003c/small\u003e\n\nRFAPI is a network request library specially designed for API requests. It is a URL session wrapper base on AFNetworking.\n\n## Feature\n\n* It uses rules to create requests and process responses instead of stitching URLs in code. No more decode models manually and add additional error handling logic.\n* The request process can be bound to the loading progress and UI control status.\n* Beautiful request method, more readable than chain call, easy to extend.\n* Obtain and cancel requests through the specific and grouped identifiers. You can control a request without passing the request object in different code contexts.\n* Automatic model decoding supports different libraries.\n* Multiple request completion callbacks, convenient for various usage scenarios, centralized error handling, automatic error handling.\n\n## Disadvantage\n\nThe biggest problem of RFAPI is being too old. In 2014, the design and 95% of the implementation of v1 were completed. After that, there are only few minor changes in many years. Although good design is not outdated, the related technology stack has been updated. If you still use NSOperation to manage requests, if there is no URL session, no Swift, no Codable, then it's not outdated.\n\nI start to upgrade it to v2 at the end of 2019. The primary goal is to support AFNetworking v3. The premise is to maintain compatibility with the old version as much as possible. A new interface design has been implemented. The user experience in Swift has been improved. It cannot be completely renovated means:\n\n* The interface of the main class for overloading is difficult to use in Swift. They are designed for Objective-C. The flexible design of Objective-C becomes strange when transferred into Swfit.\n* Codable is not supported, it is troublesome to support a Swift proprietary feature.\n* The URL session feature is currently not fully utilized. Currently, only data tasks are implemented. Download and upload tasks are not supported yet.\n* The download feature is limited. Please check other libraries if you needs a downloader.\n\nIn the future, encapsulation of Alamofire will open another project. This library will not be rewritten in Swift.\n\n## Usage\n\n## CocoaPods Install\n\nOnly integration through CocoaPods is supported due to dependent factors. There is no support plan for SPM and Carthage.\n\n```ruby\npod 'RFAPI'\n```\n\nSpecify develop branch to install the latest version:\n\n```ruby\npod 'RFAPI',\n    :git =\u003e 'https://github.com/RFUI/RFAPI.git',\n    :branch =\u003e 'develop'\n```\n\n## Define an API\n\nUnlike most network libraries, you cannot make a request with a url object. Instead, RFAPI uses API define objects to describe not only how to make requests, but also how to handle responses.\n\n```swift\nlet define = RFAPIDefine()\ndefine.name = RFAPIName(rawValue: \"TopicListRecommended\")\ndefine.path = \"https://example.com/api/v2/topics/recommended\"\ndefine.method = \"GET\"\ndefine.needsAuthorization = true\ndefine.responseExpectType = .objects\ndefine.responseClass = \"TopicEntity\"\n```\n\nGenerally, a default define should be created. After that, you only need to provide different parts from the default define when creating other defines. Example of setting default rules:\n\n```swift\nlet api = ... // RFAPI instance\nlet defaultDefine = RFAPIDefine()\ndefaultDefine.baseURL = URL(string: \"https://example.com/\")\ndefaultDefine.pathPrefix = \"api/v2/\"\ndefaultDefine.method = \"GET\"\ndefaultDefine.needsAuthorization = true\napi.defineManager.defaultDefine = defaultDefine\n```\n\nWith the default define, the above API definition can be simplified to:\n\n```swift\nlet define = RFAPIDefine()\ndefine.name = RFAPIName(rawValue: \"TopicListRecommended\")\ndefine.path = \"topics/recommended\"\ndefine.responseExpectType = .objects\ndefine.responseClass = \"TopicEntity\"\n```\n\nThe more recommended way is to load the defines from the configuration file. You can load the defines from a local file (such as json, plist), or even get the configuration from the server. eg:\n\n```json\n{\n  \"DEFAULT\": {\n    \"Base\": \"https://example.com/\",\n    \"Path Prefix\": \"api/v2/\",\n    \"Method\": \"GET\",\n    \"Authorization\": true\n  },\n  \"TopicListRecommended\": {\n    \"Path\": \"topics/recommended\",\n    \"Response Type\": 3,\n    \"Response Class\": \"TopicEntity\"\n  },\n  \"UserLogin\": {\n    \"Method\": \"POST\",\n    \"Path\": \"user/login\",\n    \"Authorization\": false,\n    \"Response Type\": 2,\n    \"Response Class\": \"LoginResponseEntity\"\n  },\n  ...\n}\n```\n\nThe file configuration should be a dictionary of type `[String: [String: Any]]`, key is the API name, and `DEFAULT` is for the default define. With a configuration file, it can be loaded into the define manager, and then the request can be make directly with the API name. eg:\n\n```swift\nlet rules = ... // Configuration loaded\nlet api = ...   // RFAPI instance\ndefineManager.setDefinesWithRulesInfo(rules)\n```\n\nBy default, the content format of request and response are both JSON. You can modify it globally by changing the `defaultRequestSerializer` and `defaultResponseSerializer` properties of the define manager. If you need to adjust an individual API, you can specify the serializer type in the API define. eg:\n\n```json\n{\n  \"FormUpload\": {\n    \"Method\": \"POST\",\n    \"Path\": \"common/formupload\",\n    \"Serializer\": \"AFHTTPRequestSerializer\",\n    \"Response Serializer\": \"AFPropertyListResponseSerializer\",\n    \"Response Type\": 1\n  }\n}\n```\n\nOther configuration file examples: [Demo Project Configuration](https://github.com/RFUI/RFAPI/blob/develop/Example/iOS-Swift/TestAPIDefine.plist)，[iOS Project Template/APIDefine.plist](https://github.com/BB9z/iOS-Project-Template/blob/master/App/Networking/APIDefine.plist)\n\n### Making requests\n\nYou can directly pass the define object when making a request; if the define has been in the define manager, you can directly pass the API name. Pass all other parameters through the context object.\n\n```swift\nlet api = ... // RFAPI instance\napi.request(name: \"TopicListRecommended\") { c in\n    c.parameters = [\"page\": 1, \"page_size\": 20]\n    c.loadMessage = \"List Loading\"\n    c.success { _, rsp in\n        guard let topics = rsp as? [TopicEntity] else { fatalError() }\n        ...\n    }\n}\n```\n\nFor more usage, checkout [Cookbook](Documents/Cookbook.md)\n\n### Differences from the general\n\n* Cancellation is not considered as failure\n\n    When a request is cancelled, the failure callback will not be called. Also a failure callback will never be called with an `NSURLErrorCancelled` error parameter.\n\n    But you could get an `NSURLErrorCancelled` error from a RFAPITask object in the finished or completion callback.\n\n* Most parameters are mutable\n\n    Except for properties related to define, most of the parameters passed through the context will not be copied. It's your free to pass mutable array, dictionary, string or any others and change these value after the request has been made. RFAPI allows you to do that and thinks you know what you are doing.\n\n### Localization\n\nYou can localize RFAPI built-in messages by putting localizable strings into the default table of the main bundle.\n\nSamples:\n\n* [en](Example/iOS-Swift/en.lproj/Localizable.strings)\n* [zh-Hans](Example/iOS-Swift/zh-Hans.lproj/Localizable.strings)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frfui%2Frfapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frfui%2Frfapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frfui%2Frfapi/lists"}