{"id":29631878,"url":"https://github.com/javiermanzo/harbor","last_synced_at":"2025-07-21T12:05:47.959Z","repository":{"id":65928063,"uuid":"602568744","full_name":"javiermanzo/Harbor","owner":"javiermanzo","description":"Harbor is a library for making API requests in Swift in a simple way using async/await.","archived":false,"fork":false,"pushed_at":"2025-07-20T20:53:01.000Z","size":2626,"stargazers_count":16,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-20T21:24:44.714Z","etag":null,"topics":["ios","jsonrpc","macos","networking","rest","swift","swiftpackage","swiftpackagemanager","urlsession"],"latest_commit_sha":null,"homepage":"","language":"Swift","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/javiermanzo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-02-16T13:45:06.000Z","updated_at":"2025-02-10T21:28:14.000Z","dependencies_parsed_at":"2025-07-20T21:16:22.742Z","dependency_job_id":"4502a1dc-c1a2-485c-885c-e0e6399e89cf","html_url":"https://github.com/javiermanzo/Harbor","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/javiermanzo/Harbor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javiermanzo%2FHarbor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javiermanzo%2FHarbor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javiermanzo%2FHarbor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javiermanzo%2FHarbor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/javiermanzo","download_url":"https://codeload.github.com/javiermanzo/Harbor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/javiermanzo%2FHarbor/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266296815,"owners_count":23907015,"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","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["ios","jsonrpc","macos","networking","rest","swift","swiftpackage","swiftpackagemanager","urlsession"],"created_at":"2025-07-21T12:05:47.194Z","updated_at":"2025-07-21T12:05:47.943Z","avatar_url":"https://github.com/javiermanzo.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003cp align=\"center\" width=\"100%\"\u003e\n    \u003cimg width=\"40%\" src=\"https://raw.githubusercontent.com/javiermanzo/Harbor/main/Resources/Harbor.png\"\u003e \n\u003c/p\u003e\n\n![Release](https://img.shields.io/github/v/release/javiermanzo/Harbor?style=flat-square)\n![CI](https://img.shields.io/github/actions/workflow/status/javiermanzo/Harbor/swift.yml?style=flat-square)\n[![Swift](https://img.shields.io/badge/Swift-5.9_6.0-orange?style=flat-square)](https://img.shields.io/badge/Swift-5.9_5.10_6.0-Orange?style=flat-square)\n[![Platforms](https://img.shields.io/badge/Platforms-macOS_iOS-yellowgreen?style=flat-square)](https://img.shields.io/badge/Platforms-macOS_iOS_tvOS_watchOS_vision_OS_Linux_Windows_Android-Green?style=flat-square) \n![Swift Package Manager(https://swiftpackageindex.com/javiermanzo/Harbor)](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)\n![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Harbor.svg?style=flat-square)\n\nHarbor is a library for making API requests in Swift in a simple way using async/await.\n\n## Table of Contents\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n  - [CocoaPods](#cocoapods)\n  - [Swift Package Manager](#swift-package-manager)\n- [Usage](#usage)\n  - [Configuration](#configuration)\n    - [Default Headers](#default-headers)\n    - [Auth Provider](#auth-provider)\n    - [Custom URLSession](#custom-urlsession)\n    - [mTLS Support](#mtls-support)\n    - [SSL Pinning](#ssl-pinning)\n  - [Request Protocols](#request-protocols)\n    - [HGetRequestProtocol](#hgetrequestprotocol)\n    - [HPostRequestProtocol](#hpostrequestprotocol)\n    - [HPatchRequestProtocol](#hpatchrequestprotocol)\n    - [HPutRequestProtocol](#hputrequestprotocol)\n    - [HDeleteRequestProtocol](#hdeleterequestprotocol)\n    - [HRequestWithResultProtocol](#hrequestwithresultprotocol)\n  - [Request Calling](#request-calling)\n  - [Response](#response)\n    - [HResponse](#hresponse)\n    - [HResponseWithResult](#hresponsewithresult)\n  - [Cancel Request](#cancel-request)\n  - [Debug](#debug)\n  - [JSON RPC](#json-rpc)\n    - [Installation](#installation-1)\n    - [Configuration](#configuration-1)\n      - [Set URL](#set-url)\n      - [Set JSON RPC Version](#set-json-rpc-version)\n    - [Request Protocol](#request-protocol)\n      - [HJRPCRequestProtocol](#hjrpcrequestprotocol)\n    - [Response](#response-1)\n- [Mocks](#mocks)\n- [Contributing](#contributing)\n- [Author](#author)\n- [License](#license)\n\n## Features\n\n- [x] Rest Requests\n- [x] JSON RPC Requests\n- [x] Auth provider handler\n- [x] Multipart Post Requests\n- [x] Retry Requests\n- [x] Cancel Request\n- [x] Debug Requests\n- [x] cURL Command Output\n- [x] Default Headers\n- [x] Custom URLSession\n- [x] mTLS Certificate\n- [x] SSL Pinning\n- [x] Swift 6 Compatible\n- [x] Mock Requests\n\n## Requirements\n\n- Swift 5.9+\n- iOS 15.0\n\n## Installation\nYou can add Harbor to your project using [CocoaPods](https://cocoapods.org/) or [Swift Package Manager](https://swift.org/package-manager/).\n\n### CocoaPods\nAdd the following line to your Podfile:\n\n```ruby\npod 'Harbor'\n```\n\n### Swift Package Manager\nAdd the following to your `Package.swift` file:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/javiermanzo/Harbor.git\")\n]\n```\n\n## Usage\n\n### Configuration\nThis provides a centralized way to manage common configuration.\n\n#### Default Headers\nYou can include default headers in every request.\n\nTo configure the default headers:\n\n```swift\nawait Harbor.setDefaultHeaderParameters([\n    \"MY_CUSTOM_HEADER\": \"VALUE\"\n])\n```\n\n#### Auth Provider\nYou can implement the `HAuthProviderProtocol` if you need to handle authentication. Use the `setAuthProvider` method of the `Harbor` class to set the authentication provider.\n\nYou need to create a class that implements `HAuthProviderProtocol`:\n\n```swift\nclass MyAuthProvider: HAuthProviderProtocol {\n    func getAuthorizationHeader() async -\u003e HAuthorizationHeader {\n        // Return a HAuthorizationHeader instance\n    }\n    \n    func authFailed() async {\n        // This method is called when the request receives a 401 status code\n    }\n}\n```\n\nAfter that, set your Auth provider:\n\n```swift\nawait Harbor.setAuthProvider(MyAuthProvider())\n```\n\nIf the request class has the `needsAuth` property set to `true`, Harbor will call the `getAuthorizationHeader` method of the authentication provider to get the `HAuthorizationHeader` instance to set it in the header before executing the request.\n\n#### Custom URLSession\nHarbor allows you to set a custom `URLSession` for your requests, providing flexibility for advanced configurations such as custom caching, timeout settings, or additional protocols.\n\nTo set a custom `URLSession`, use the `setCustomURLSession` method:\n\n```swift\nlet customSession = URLSession(configuration: .default)\nawait Harbor.setCustomURLSession(customSession)\n```\n\n#### mTLS Support\nHarbor supports mutual TLS (mTLS) for enhanced security in API requests. This feature allows clients to present certificates to the server, ensuring both the client and server authenticate each other.\n\nTo set up mTLS, use the `setMTLS` method:\n\n```swift\nlet mTLS = HmTLS(p12FileUrl: yourP12FileUrl, password: \"yourPassword\")\nawait Harbor.setMTLS(mTLS)\n```\n\n#### SSL Pinning\nHarbor supports SSL Pinning to enhance the security of your API requests. SSL Pinning ensures that the client checks the server's certificate against a known pinned certificate, adding an additional layer of security.\n\nTo configure SSL Pinning, use the `setSSlPinningSHA256` method:\n\n```swift\nlet sslPinningSHA256 = \"yourSHA256CertificateHash\"\nawait Harbor.setSSlPinningSHA256(sslPinningSHA256)\n```\n\n### Request Protocols\nTo make a request using Harbor, you need to create a class that implements one of the following protocols.\n\n#### HGetRequestProtocol\nUse the `HGetRequestProtocol` protocol if you want to send a GET request.\n\n##### Extra Properties:\n- `queryParameters`: A dictionary of query parameters that will be added to the URL.\n- `Model`: The result of the request will be parsed to this entity.\n\n#### HPostRequestProtocol\nUse the `HPostRequestProtocol` protocol if you want to send a POST request.\n\n##### Extra Properties:\n- `bodyParameters`: A dictionary of parameters that will be included in the body of the request.\n- `bodyType`: Specifies the type of data being sent in the body of the request. It can be either json or multipart.\n\n#### HPatchRequestProtocol\nUse the `HPatchRequestProtocol` protocol if you want to send a PATCH request.\n\n##### Extra Properties:\n- `bodyParameters`: A dictionary of parameters that will be included in the body of the request.\n- `bodyType`: Specifies the type of data being sent in the body of the request. It can be either json or multipart.\n\n#### HPutRequestProtocol\nUse the `HPutRequestProtocol` protocol if you want to send a PUT request.\n\n##### Extra Properties:\n- `bodyParameters`: A dictionary of parameters that will be included in the body of the request.\n- `bodyType`: Specifies the type of data being sent in the body of the request. It can be either json or multipart.\n\n#### HDeleteRequestProtocol\nUse the `HDeleteRequestProtocol` protocol if you want to send a DELETE request.\n\n#### HRequestWithResultProtocol\nUse the `HRequestWithResultProtocol` protocol if you want to parse the response into a specific model. This protocol requires you to define the type of model you expect in the response.\n\n##### Extra Properties:\n- `Model`: The result of the request will be parsed to this entity.\n\n### Request Calling\nOnce the request class is created, you can execute the request using the `request` method.\n\n```swift\nTask {\n    let response = await MyRequestWithResult().request()\n}\n```\n\n### Response\n\n#### HResponse\nIf you use a protocol different from `HGetRequestProtocol` or `HRequestWithResultProtocol`, the result of calling `request()` will be an `HResponse` enum.\n\n```swift\nswitch response {\ncase .success:\n    break\ncase .error(let error):\n    break\n}\n```\n\n#### HResponseWithResult\nIf you use `HGetRequestProtocol` or `HRequestWithResultProtocol`, the result of calling `request()` will be an `HResponseWithResult` enum.\n\n```swift\nswitch response {\ncase .success(let result):\n    break\ncase .error(let error):\n    break\n}\n```\n\n### Cancel Request\nYou can cancel the task of the request if it is running. `request()` will return `cancelled` as an error case.\n\n```swift\nlet task = Task {\n    let response = await MyRequestWithResult().request()\n}\ntask.cancel()\n```\n\n### Debug\nYou can print debug information about your request using the `HDebugRequestProtocol` protocol. Implement the protocol in the request class.\n\n```swift\nclass MyRequest: HRequestWithResultProtocol, HDebugRequestProtocol {\n    var debugType: HDebugRequestType = .requestAndResponse\n    \n    // ...\n}\n```\n\n`debugType` defines what you want to print in the console. The options are `none`, `request`, `response`, or `requestAndResponse`.\n\nWhen your request is called, you will see in the Xcode console the information about your request.\n\n\n## JSON RPC\nHarbor also supports JSON RPC via the `HarborJRPC` package.\n\n### Installation\nTo use HarborJRPC, add the following import to your file:\n\n```swift\nimport HarborJRPC\n```\n\n### Configuration\n\n#### Set URL\nUse this method to set the URL for the JSON RPC requests:\n\n```swift\nHarborJRPC.setURL(\"https://api.example.com/\")\n```\n\n#### Set JSON RPC Version\nUse this method to set the JSON RPC version:\n\n```swift\n// It uses 2.0 as default \nHarborJRPC.setJRPCVersion(\"2.0\")\n```\n### Request Protocol\n\n#### HJRPCRequestProtocol\nUse the `HJRPCRequestProtocol` protocol if you want to send a JRPC request.\n\n##### Properties:\n- `Model`: The model that conforms to the `Codable` protocol, representing the expected response structure.\n- `method`: A string that represents the JRPC method to be called.\n- `needsAuth`: A boolean indicating whether the request requires authentication.\n- `retries`: The number of retries in case the request fails.\n- `headers`: An optional dictionary containing any additional headers to be included in the request.\n- `parameters`: An optional dictionary of parameters to be included in the request.\n\n### Response\nTo configure a request using HarborJRPC, create a struct or class that implements `HJRPCRequestProtocol`. The result of calling `request()` will be an `HJRPCResponse`:\n\n```swift\nswitch response {\ncase .success(let result):\n    break\ncase .error(let error):\n    break\n}\n```\n\n## Mocks\nHarbor allows you to register and manage mocks to facilitate testing your API requests.\n\n### HMock\nUse `HMock` to declare mock responses for your requests.\n\n#### Properties:\n- `request`: The request type that conforms to `HRequestBaseRequestProtocol` for which the mock is being set.\n- `statusCode`: The HTTP status code to return.\n- `jsonResponse`: A `String` representing the JSON response. This will be decoded as the expected model for your request.\n- `error`: An optional `HRequestError` if you want to simulate an error response.\n- `delay`: An optional delay (in seconds) before returning the mock response, to simulate network latency.\n\n### Register a Mock\nTo register a mock, use the `register(mock:)` method. This will allow you to simulate responses instead of making actual API calls.\n\n```swift\nlet mock = HMock(\n    ///\n)\nawait Harbor.register(mock: mock)\n```\n\n### Registering a Success Mock\n\n```swift\nlet jsonResponse = \"\"\"\n    { \"name\": \"John Doe\" }\n\"\"\"\nlet mock = HMock(\n    request: MyGetUsersRequest.self,\n    statusCode: 200,\n    jsonResponse: jsonResponse\n)\nawait Harbor.register(mock: mock)\n```\n\n### Registering a Error Mock\n\n```swift\nlet mock = HMock(\n    request: MyGetUsersRequest.self,\n    statusCode: 401,\n    error: .authNeeded\n)\nawait Harbor.register(mock: mock)\n```\n\n### Using Mocks Only in Debug Mode\nYou can configure mocks to only be used in #DEBUG, preventing them from affecting production environments. The default value is *true*.\n\n```swift\nawait Harbor.setMocksOnlyInDebug(false)\n```\n\n### Removing a Specific Mock\nIf you need to remove a specific mock, use the `remove(mock:)` method.\n\n```swift\nawait Harbor.remove(mock: mock)\n```\n\n### Removing All Mocks\nTo clear all registered mocks, use the `removeAllMocks()` method.\n\n```swift\nawait Harbor.removeAllMocks()\n```\n\n### Complete Example\nBelow is a complete example demonstrating how to set up and use mocks with Harbor:\n\n```swift\n\nTask {\n    let jsonResponse = \"\"\"\n        { \"users\": [{ \"id\": 1, \"name\": \"Alice\" }] }\n    \"\"\"\n    let userMock = HMock(\n        request: MyGetUsersRequest.self,\n        statusCode: 200,\n        jsonResponse: jsonResponse\n    )\n\n    // Register the mock\n    await Harbor.register(mock: userMock)\n\n    // Perform a request that will use the registered mock\n    let response = await MyGetUsersRequest().request()\n    switch response {\n    case .success(let users):\n        // You will receive the mocked response here\n        print(\"Users:\", users)\n    case .error(let error):\n        break\n    }\n}\n```\n\n## Contributing\nIf you run into any problems, please submit an [issue](https://github.com/javiermanzo/Harbor/issues). [Pull requests](https://github.com/javiermanzo/Harbor/pulls) are also welcome! \n\n## Author\nHarbor was created by [Javier Manzo](https://www.linkedin.com/in/javiermanzo/).\n\n## License\nHarbor is available under the MIT license. See the [LICENSE](https://github.com/javiermanzo/Harbor/blob/main/LICENSE.md) file for more info.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaviermanzo%2Fharbor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaviermanzo%2Fharbor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaviermanzo%2Fharbor/lists"}