Building42 / Telegraph

Secure Web Server for iOS, tvOS and macOS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Asynchronous response in `respond`

jfgrang opened this issue · comments

I am looking for a way to make respond asynchronous.
In some cases I don't have a local file and I want to download it then deliver it.

The given example seems to only manage local synchronous requests. How would you perform a network download in that nextHandlerchain ?

  public func respond(to request: HTTPRequest, nextHandler: HTTPRequest.Handler) throws -> HTTPResponse? {
    // If this is a GET request, pass it to the next handler
    if request.method == .GET {
      return try nextHandler(request)
    }
    // Otherwise return 403 - Forbidden
    return HTTPResponse(.forbidden, content: "Only GET requests are allowed")
  }
}

I was considering to add a waitHandler that checks the status of a Session but it seems a little odd.

Thanks for your help

@jfgrang Unfortunately Telegraph doesn't support asynchronous responses at this moment. You might be able to implement it by creating your own Server class, inherit from the existing Server class and overriding some of the request handling methods there.

It would be great if we could support a closure return type in a handler, but that requires some refactoring.

Maybe next weekend I'll be able to make some updates to the framework. Add a Package.swift and things like that.

hello @yvbeek , is there any news about this subject? i would like to intercept and execute some requests to a distant server before returning an HTTPResponse, but i don't see anything to do that. Am i wrong?

@tlemansec Sorry for my late reply. Adding Swift Package Manager support and fixing the iOS 13 issue were way more difficult than I anticipated.

After this release I'll have a look at async reponses.

Version 0.28 is now available 🚀

To support asynchronous requests / responses I'm going to have to make some changes to the Server, Route and Handler classes. The most difficult part is the request handler chain, I have to somehow make that asynchronous.

I hope to have some time next weekend to work on it.

@jfgrang I solved by using a DispatchGroup. Maybe is not optimal for scalability/concurrency, but for small async operation should be fine.
Here just an example calling a fake function process that returns a string:

private func handleRequest(request: HTTPRequest) -> HTTPResponse {
        var result: String?

        let group = DispatchGroup()
        group.enter()

        DispatchQueue.global().async {
            process { value in 
                 result = value
                 group.leave()
            }
        }

        // wait ...
        group.wait()

        return HTTPResponse(content: result ?? "-")
    }

It looks like this thread has gone quiet but are there any updates on supporting this in Telegraph without having to work-around and use Dispatch Groups?

@paultiarks Unfortunately it is going to take quite a bit of (re)architecture and dev work to add this to the library. As I no longer use Telegraph in my day-to-day work, it might take a while for me to look into this.

The DispatchGroup can be a workaround for now and should probably scale well enough for Telegraph's use cases. I'm also happy to look into PRs if there are people who have implemented this feature.