Skip to content

Commit

Permalink
support response references
Browse files Browse the repository at this point in the history
  • Loading branch information
yonaskolb committed Jan 11, 2018
1 parent 403393e commit ee1e355
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 16 deletions.
14 changes: 14 additions & 0 deletions Sources/Swagger/Reference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ public class Reference<T: JSONObjectConvertible> {
func resolve(with value: T) {
_value = value
}

func getReferenceComponent(index: Int) -> String? {
let components = string.components(separatedBy: "/")
guard components.count > index else { return nil }
return components[index]
}

public var referenceType: String? {
return getReferenceComponent(index: 1)
}

public var referenceName: String? {
return getReferenceComponent(index: 2)
}
}

public enum PossibleReference<T: JSONObjectConvertible>: JSONObjectConvertible {
Expand Down
37 changes: 21 additions & 16 deletions Sources/Swagger/SwaggerSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,28 +122,32 @@ extension SwaggerSpec: JSONObjectConvertible {

func resolveReferences() {

func resolveDefinitionReference(_ reference: Reference<Schema>) {
let components = reference.string.components(separatedBy: "/")
if components.count == 3 && components[0] == "#" && components[1] == "definitions" {
let name = components[2]
if let schema = definitions.first(where: { $0.name == name }) {
reference.resolve(with: schema.value)
}
func resolvePossibleReference<T>(_ reference: PossibleReference<T>, objects: [SwaggerObject<T>], type: String) {
if case let .reference(reference) = reference {
resolveReference(reference, objects: objects, type: type)
}
}

func resolveParameterReference(_ reference: PossibleReference<Parameter>) {
if case let .reference(reference) = reference {
let components = reference.string.components(separatedBy: "/")
if components.count == 3 && components[0] == "#" && components[1] == "parameters" {
let name = components[2]
if let param = parameters.first(where: { $0.name == name }) {
reference.resolve(with: param.value)
}
}
func resolveReference<T>(_ reference: Reference<T>, objects: [SwaggerObject<T>], type: String) {
if reference.referenceType == type,
let name = reference.referenceName,
let object = objects.first(where: { $0.name == name }) {
reference.resolve(with: object.value)
}
}

func resolveDefinitionReference(_ reference: Reference<Schema>) {
resolveReference(reference, objects: definitions, type: "definitions")
}

func resolveParameterReference(_ reference: PossibleReference<Parameter>) {
resolvePossibleReference(reference, objects: parameters, type: "parameters")
}

func resolveResponseReference(_ reference: PossibleReference<Response>) {
resolvePossibleReference(reference, objects: responses, type: "responses")
}

func resolveSchema(_ schema: Schema) {
switch schema.type {
case let .reference(reference): resolveDefinitionReference(reference)
Expand Down Expand Up @@ -179,6 +183,7 @@ extension SwaggerSpec: JSONObjectConvertible {
path.operations.forEach {
$0.pathParameters.forEach(resolveParameterReference)
$0.operationParameters.forEach(resolveParameterReference)
$0.responses.map{$0.response}.forEach(resolveResponseReference)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,59 @@ extension TestSpec {
/** string response */
case status200(String)

/** 400 response */
case status400(String)

public var success: String? {
switch self {
case .status200(let response): return response
default: return nil
}
}

public var failure: String? {
switch self {
case .status400(let response): return response
default: return nil
}
}

/// either success or failure value. Success is anything in the 200..<300 status code range
public var responseResult: APIResponseResult<String, String> {
if let successValue = success {
return .success(successValue)
} else if let failureValue = failure {
return .failure(failureValue)
} else {
fatalError("Response does not have success or failure response")
}
}

public var response: Any {
switch self {
case .status200(let response): return response
case .status400(let response): return response
}
}

public var statusCode: Int {
switch self {
case .status200: return 200
case .status400: return 400
}
}

public var successful: Bool {
switch self {
case .status200: return true
case .status400: return false
}
}

public init(statusCode: Int, data: Data) throws {
switch statusCode {
case 200: self = try .status200(JSONDecoder.decode(data: data))
case 400: self = try .status400(JSONDecoder.decode(data: data))
default: throw APIError.unexpectedStatusCode(statusCode: statusCode, data: data)
}
}
Expand Down
7 changes: 7 additions & 0 deletions Specs/TestSpec/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ paths:
description: string response
schema:
type: string
400:
$ref: '#/responses/400'
definitions:
User:
type: object
Expand Down Expand Up @@ -105,3 +107,8 @@ definitions:
description: definition with only additional properties
type: object
additionalProperties: true
responses:
400:
description: 400 response
schema:
type: string

0 comments on commit ee1e355

Please sign in to comment.