|
| 1 | +## Relax Type Constraints for Codable Routing |
| 2 | +* Proposal: KIT-0004 |
| 3 | +* Authors: [David Jones](https://github.com/djones6) |
| 4 | +* Review Manager: [Lloyd Roseblade](https://github.com/lroseblade) |
| 5 | +* Status: DRAFT |
| 6 | +* Decision Notes: Rationale, Additional Commentary |
| 7 | +* Previous Revision: 1 |
| 8 | +* Previous Proposal: N/A |
| 9 | + |
| 10 | +### Introduction |
| 11 | +Codable Routing currently requires that types used as Input or Output conform to `Codable`, ie. `Encodable & Decodable`. This proposal is to relax the requirements on those types to simply `Decodable` for Input and `Encodable` for Output types. |
| 12 | + |
| 13 | +### Motivation |
| 14 | +Users are currently required to support both Encodable and Decodable when creating types for use with Codable Routing. Whilst the compiler can often synthesise the encode/decode functions, there are cases where the user must provide an implementation, such as an enum with associated values. |
| 15 | + |
| 16 | +If the user wants to use that type only in one direction - say if they want to receive data in a type-safe way from an existing service - they are obliged to implement an unnecessary encode/decode function just to satisfy the type requirements. |
| 17 | + |
| 18 | +Example: https://github.com/IBM-Swift/Kitura/issues/1235 |
| 19 | + |
| 20 | +### Proposed solution |
| 21 | +In the Codable Router extension and its associated closure aliases, |
| 22 | +- Replace each instance of `<I: Codable>` with `<I: Decodable>` |
| 23 | +- Replace each instance of `<O: Codable>` with `<O: Encodable>` |
| 24 | + |
| 25 | +This is not an API-breaking change: |
| 26 | +- `Decodable` and `Encodable` are a subset of `Codable`, so existing Codable types can be used, and can continue to be used for both the input and output type |
| 27 | +- Kitura's `Router` class is not `open` (and so cannot have been subclassed outside of the Kitura package). |
| 28 | + |
| 29 | +To facilitate receiving a `Decodable` type via a PUT or POST, without requiring an `Encodable` type be returned, this proposal relaxes the rules for responding with an `(Encodable?, RequestError?)`, so that rather than requiring exactly one of these to be non-nil, the following are also permitted: |
| 30 | +- `(nil, successStatus)`: respond successfully with the specified status code and no body |
| 31 | +- `(nil, nil)`: respond successfully with the default status for that method and no body |
| 32 | + |
| 33 | +Where `successStatus` is a `RequestError` in the 2xx (success) range. |
| 34 | + |
| 35 | +And similarly for `(Identifier?, Encodable?, RequestError?)`: |
| 36 | +- `(id, nil, successStatus)`: respond successfully with the Location header, specified status code and no body |
| 37 | +- `(id, nil, nil)`: respond successfully with the Location header, default status for that method and no body |
| 38 | + |
| 39 | +where `id` is a valid `Identifier`. |
| 40 | + |
| 41 | +### No change to the KituraKit client |
| 42 | +Although KituraKit's API mirrors that of Kitura's Codable Routing, I felt it makes sense to leave KituraKit's API in terms of `Codable` input and output types: KituraKit shares types with a Kitura back-end, and thus those types must be both encodable and decodable. It is not intended that KituraKit be used to interact with non-codable routes. |
| 43 | + |
| 44 | +By contrast, it is reasonable to expect Kitura to interact with existing services and clients in a type-safe way. |
| 45 | + |
| 46 | +### Detailed design |
| 47 | +A working prototype exists here: |
| 48 | +- https://github.com/IBM-Swift/Kitura/compare/issue_1235 (https://github.com/IBM-Swift/Kitura/pull/1242) |
| 49 | +- https://github.com/IBM-Swift/KituraContracts/compare/issue_1235 (https://github.com/IBM-Swift/KituraContracts/pull/18) |
| 50 | + |
| 51 | +### Alternatives considered |
| 52 | +None |
0 commit comments