HTTP请求在尝试通过API报告不受欢迎的通信时失败。

huangapple go评论66阅读模式
英文:

HTTP Request Fails Trying to Report Unwanted Communication Report via API

问题

我根据此处的描述创建了一个不受欢迎的通信报告扩展:https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_call_spam_reporting

按照说明进行操作,并成功获得了扩展类中的报告回调,但当我尝试向我的HTTPS服务器发出API请求时,在控制台日志中的某个地方出现了以下错误:

nw_resolver_can_use_dns_xpc_block_invoke Sandbox does not allow access to com.apple.dnssd.service

Task <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1> finished with error [-1003] Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={_kCFStreamErrorCodeKey=-72000, NSUnderlyingError=0x282d5c600 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, _kCFStreamErrorCodeKey=-72000, _kCFStreamErrorDomainKey=10}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1>"), NSLocalizedDescription=A server with the specified hostname could not be found., NSErrorFailingURLStringKey=https://sub.domain.com/debug, NSErrorFailingURLKey=https://sub.domain.com/debug, _kCFStreamErrorDomainKey=10}

所以基本上由于沙箱限制,DNS查找失败了,但我无法允许应用程序访问沙箱,这似乎是OSX特定的能力。

以下是负责API报告的我的代码示例:

func reportToAPI(for request: ILClassificationRequest) {
    
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    
    guard let url = URL(string: "https://sub.domain.com/debug") else {
        return
    }
    
    var request = URLRequest(url: url)
    
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = try? JSONSerialization.data(withJSONObject: payload, options: .fragmentsAllowed)
    
    let task = URLSession.shared.dataTask(with: request) { data, _, error in
        guard let data = data, error == nil else {
            return
        }
        
        do {
            let response = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print(response)
        } catch {
            
        }
    }
    task.resume()
}

我还在扩展和主应用程序的目标上设置了相关域,如classificationreport:sub.domain.com和domain.com,以及我的apple-app-site-association文件上传如下:

{
    "classificationreport": {
        "apps": ["L***.com.b***.smsreporting.unwantedreporting","L***.com.b***.smsreporting"]
    }
}

如果需要帮助和指导,将不胜感激,因为我在这一点上被卡住了,缺乏文档使事情变得更加困难。

编辑:我正在测试自己的开发者帐户上,这是个人会员,不是组织性的,如果这有关系的话。

英文:

I created an Unwanted Communication Reporting Extension as per described here: https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_call_spam_reporting

Followed the instructions and was able to get the report callback in my extension class, but when I try to make an API request to my HTTPS server, somewhere along the console log I get

nw_resolver_can_use_dns_xpc_block_invoke Sandbox does not allow access to com.apple.dnssd.service

and

Task <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1> finished with error [-1003] Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={_kCFStreamErrorCodeKey=-72000, NSUnderlyingError=0x282d5c600 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, _kCFStreamErrorCodeKey=-72000, _kCFStreamErrorDomainKey=10}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1>"), NSLocalizedDescription=A server with the specified hostname could not be found., NSErrorFailingURLStringKey=https://sub.domain.com/debug, NSErrorFailingURLKey=https://sub.domain.com/debug, _kCFStreamErrorDomainKey=10}

So basically the dns lookup fails due to a sandbox restriction, but I was not able to allow the app sandbox access, that seems like a OSX specific capability.

Here is my code example that is in charge of the API reporting:

func reportToAPI(for request: ILClassificationRequest) {
    
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    
    guard let url = URL(string: "https://sub.domain.com/debug") else {
        return
    }
    
    var request = URLRequest(url: url)
    
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = try? JSONSerialization.data(withJSONObject: payload, options: .fragmentsAllowed)
    
    let task = URLSession.shared.dataTask(with: request) { data, _, error in
        guard let data = data, error == nil else {
            return
        }
        
        do {
            let response = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print(response)
        } catch {
            
        }
    }
    task.resume()
}

I also have my associated domains set up on both extension and main app's target as classificationreport:sub.domain.com and domain.com, as well as my apple-app-site-association file uploaded as this:

{
"classificationreport": {
    "apps": ["L***.com.b***.smsreporting.unwantedreporting","L***.com.b***.smsreporting"]
}

Any help and guidance is appreciated as I am stuck at this point and lack of documentation on this is making things harder.

Edit: I am testing this on my own developer account, which is an individual membership, not organizational, if that matters.

答案1

得分: 1

在不需要的通信报告扩展中,似乎您调用了reportToAPI()

然而,如果您正确地在.entitlement中添加了apple-app-site-associationAssociation Domain,则无需自己创建URLRequest。苹果将代表您发送API请求。(我认为这是出于隐私原因,就像消息过滤扩展一样。)

因此,classificationResponse应该如下所示:

override func classificationResponse(for request: ILClassificationRequest) -> ILClassificationResponse {
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    let action: ILClassificationAction = .reportJunk  // 或 .none、.reportNotJunk、.reportJunkAndBlockSender
    let response = ILClassificationResponse(action: action)
    response.userInfo = payload

    return response
}
英文:

It seems you call reportToAPI() in Unwanted Communication Reporting Extension.

However if you add apple-app-site-association and Association Domain in .entitlement correctly. There is no need to create URLRequest by yourself. Apple will send the API on your behalf. (I think it's for privacy reasons, like Message Filter Extension.)

So classificationResponse should look like this:

override func classificationResponse(for request:ILClassificationRequest) -> ILClassificationResponse {
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    let action: ILClassificationAction = .reportJunk  // or .none, .reportNotJunk, .reportJunkAndBlockSender
    let response = ILClassificationResponse(action: action)
    response.userInfo = payload

    return response
}

答案2

得分: -5

错误消息表明由于沙盒限制,DNS查找失败。
你遇到的错误,“Sandbox does not allow access to com.apple.dnssd.service”,表明你的应用在沙盒环境中受到限制,无法访问DNS服务。

你需要允许你的应用程序沙盒访问必要的功能。启用应用程序所需的功能可能不适用于个人开发者帐户。你可能需要组织成员资格。

关于你的代码,一切似乎都很正常。但是,我建议进行一些改进来处理错误。以下是你的代码的更新版本:

func reportToAPI(for request: ILClassificationRequest) {
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    
    guard let url = URL(string: "https://sub.domain.com/debug") else {
        print("Invalid URL")
        return
    }
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: payload, options: .fragmentsAllowed)
    } catch {
        print("Failed to serialize payload")
        return
    }
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("Error: \(error.localizedDescription)")
            return
        }
        
        guard let data = data else {
            print("No data received")
            return
        }
        
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print("API response: \(json)")
        } catch {
            print("Failed to parse API response: \(error.localizedDescription)")
        }
    }
    
    task.resume()
}

更改:

  1. 改进了错误处理:
    • 添加了一个围绕负载序列化的do-catch块,以捕获任何序列化错误。
    • 为从API请求中未接收到数据的情况添加了错误处理。
    • 为解析API响应添加了错误处理。
    • 在发生错误时打印具体的错误描述。
  2. 修改了打印语句,提供更多信息反馈,例如打印API响应或指示失败原因。
英文:

The error message suggests that the DNS lookup fails due to sandbox restrictions.
The error you encountered, "Sandbox does not allow access to com.apple.dnssd.service," indicates that your app is restricted from accessing DNS services within the sandbox environment.

You need to allow your app sandbox access to the necessary capabilities. Enabling capabilities required by your app might not be possible for an individual developer account. You may need an organizational membership.

Regarding your code, everything seems to be in order. However, I would suggest making a few improvements to handle errors. Here's an updated version of your code:

func reportToAPI(for request: ILClassificationRequest) {
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    
    guard let url = URL(string: "https://sub.domain.com/debug") else {
        print("Invalid URL")
        return
    }
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: payload, options: .fragmentsAllowed)
    } catch {
        print("Failed to serialize payload")
        return
    }
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("Error: \(error.localizedDescription)")
            return
        }
        
        guard let data = data else {
            print("No data received")
            return
        }
        
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print("API response: \(json)")
        } catch {
            print("Failed to parse API response: \(error.localizedDescription)")
        }
    }
    
    task.resume()
}

Changes

  1. Improved error handling:
  • Added a do-catch block around the serialization of the payload to catch any serialization errors.
  • Added error handling for the case where no data is received from the API request.
  • Added error handling for parsing the API response.
  • Printed specific error descriptions when errors occur.
  1. Modified the print statement to provide more informative feedback, such as printing the API response or indicating the failure reason.

huangapple
  • 本文由 发表于 2023年6月19日 14:27:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76504101.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定