How to redirect a request in a Safari extension

Background:

I am working on a network privacy product. Basically I have a device that intelligently blocks requests from all device on your network if it determines that the request is not privacy friendly. i.e. google services, facebook, other ads services are blocked.


Problem:
I am building a safari extension which will let a user whitelist a page. i.e. user uses facebook heavily and some things don't work on facebook because lots of requests are blocked because they are deemed to be unsafe by the device. In this case the user does not care and from the safari extension the user can whitelist facebook.com. Now the device knows that the user has whitelisted facebook, but it doesn't know what extenal domains are called by facebook, so my safari extension needs to intercept requests to determine if they originated from a tab where facebook.com is loaded. For example googleads.com/marketing/ads. My device has a way to allow requests to go through it without blocking; and that's basically anything that goes through port 9999. In this case the safari extension needs to append port 9999 to the request making it googleads.com:9999/marketing/ads


In chrome and firefox extension I can easily hook up to the onBeforeRequest event and redirect the request via port 9999 (googleads.com:9999/marketing/ads). However I can't seem to intercept a request on a Safari app extension. I've been researching Content Blocker extensions as well, but it seems like you can only give a set of rules for blocking and only during bootstrap, it does not happen to intercept every request.

Questions:

Is it possible to accomplish what I've described above (intercepting requests and redirecting them through another port) in a safari app extension? If so what's the best way to accomplish this?


Thank you

This is currently not possible. If this is something you would like to see, please submit feedback. Thanks!

https://feedbackassistant.apple.com
This actually could be done with a content script that sets window.location.href to a new URL.
I'm now developing a Safari extension that redirects web pages, then I got here.

As timothy.hatcher said, it's shame that there is no perfect solution so far. Any workarounds I tried has some problems that they send a network request for the source URL or they are unstable. So I gave up and I just use window.location.href for now. FWIW, the code I wrote is below.

By the way, I submitted a feedback as he suggested. I hope many other people will also submit it.

Code


Swift
Code Block swift
class SafariExtensionHandler: SFSafariExtensionHandler {
    override func messageReceived(withName messageName: String, from page: SFSafariPage, userInfo: [String : Any]? = nil) {
        page.getPropertiesWithCompletionHandler { [weak self] properties in
            guard let self = self else {
                return
            }
            switch messageName {
            case "pageLoaded":
                guard let url = properties?.url else {
                    break
                }
                self.redirectIfNeeded(currentPage: page, url: url)
            default:
                break
            }
        }
    }
    override func page(_ page: SFSafariPage, willNavigateTo url: URL?) {
        guard let url = url else {
            return
        }
        redirectIfNeeded(currentPage: page, url: url)
    }
    private func redirectIfNeeded(currentPage: SFSafariPage, url: URL) {
let redirectIsNeeded = <#put your condition here#>
guard redirectIsNeeded else {
return
}
// You may need to delay this code with `DispatchQueue.main.asyncAfter(deadline:)` or something like that
// because this can't redirect a web page that has the `Location` response header.
currentPage.redirect(to: url)
    }
}
private extension SFSafariPage {
    func redirect(to url: URL) {
        dispatchMessageToScript(
            withName: "redirectPage",
            userInfo: ["url": url.absoluteString])
    }
}


Javascript
Code Block js
(function () {
    if (window.top === window) {
        safari.self.addEventListener(
            'message',
            (event) => {
                if (document.hidden) {
                    return;
                }
                switch (event.name) {
                    case 'redirectPage':
                        window.location.href = event.message.url;
                        break;
                }
            },
            false);
        safari.extension.dispatchMessage('pageLoaded');
    }
})();


How to redirect a request in a Safari extension
 
 
Q