2

I can't figure out how to get classes that implement a protocol, instantiate them, and use them, without knowing about them. Clear as mud?

example:

protocol ApiController : RequestHandler {
    var routePrefix: String { get set }
    var resources: [ApiResource] { get set }
}

extension ApiController {    
    func handleRequest(request: WebRequest, response: WebResponse) {

        var apiResourceResponse: ApiResourceResponse = ApiResourceResponse(withHttpStatus: HttpStatus.BadRequest, httpBody: "404: Not Found")

        for resource in resources {
            var foundAllParameters = true;
            if(resource.route != request.requestURI()) {
                for(param, _) in request.urlVariables {
                    if(!resource.route.contains("{\(param)}")) {
                        foundAllParameters = false;
                    }
                }
            }
            if(foundAllParameters) {
                let resourceFunc = resource.function as! (ApiRequest, ApiResponse) -> ApiResourceResponse
                apiResourceResponse = resourceFunc(ApiRequest(withWebRequest: request), ApiResponse(withWebResponse: response))
                break;
            }
        }

        response.setStatus(apiResourceResponse.httpStatus.rawValue, message: "\(apiResourceResponse.httpStatus)")
        response.appendBodyString(apiResourceResponse.httpBody);
        response.requestCompletedCallback();
    }
}

class ListingsController : ApiController {
    var routePrefix = "listings"
    var resources = [ApiResource]()

    init() {
        resources.append(ApiResource(withHttpVerb: "GET", function: getListings, route: "/"))
        resources.append(ApiResource(withHttpVerb: "GET", function: getListing, route: "/{id}"))
        resources.append(ApiResource(withHttpVerb: "GET", function: getListingBaz, route: "/{id}/baz/{bazid}"))
    }

    func getListings(withWebRequest request: ApiRequest, response: ApiResponse) -> ApiResourceResponse {
        return ApiResourceResponse(withHttpStatus: HttpStatus.Ok, httpBody: "Showing All Listings")
    }

    func getListing(withWebRequest request: ApiRequest, response: ApiResponse) -> ApiResourceResponse {
        return ApiResourceResponse(withHttpStatus: HttpStatus.Ok, httpBody: "Listings with Id: \(request.webRequest.urlVariables["id"]!)")
    }

    func getListingBaz(withWebRequest request: ApiRequest, response: ApiResponse) -> ApiResourceResponse {
        return ApiResourceResponse(withHttpStatus: HttpStatus.Ok, httpBody: "Listings with Id: \(request.webRequest.urlVariables["id"]!), BazId: \(request.webRequest.urlVariables["bazid"]!)")
    }
}

What I am wanting to do is when the application loads, a call to the following function is made, in which I have to register my routes. This works very well when I manually new up the ListingsController myself, iterate over the routes and register them:

public func PerfectServerModuleInit() {

    // Install the built-in routing handler.
    // Using this system is optional and you could install your own system if desired.
    Routing.Handler.registerGlobally()


    //register controllers, would be nice to have reflection here...
    let listingController = ListingsController()
    for resource in listingController.resources {
        Routing.Routes[resource.httpVerb, "\(listingController.routePrefix)\(resource.route)"] = { _ in return listingController}
    }
}

What I would like to do is to find ListingsController, spin up a new instance of it, and use it based on the ApiController protocol. In doing this, I could just create a new ApiController and not have to do anything but implement the protocol and it would automatically have its routes registered without me having to go in to the function and doing it manually. I am using PerfectSwift Examples - URL Routing. My approach to this might be incorrect, and I am open to suggestions. What I do not want to do is change how PerfectServer does its magic. I'm just trying to expand on it and build a framework that others can possibly use.

crizzwald
  • 1,037
  • 2
  • 14
  • 30

0 Answers0