为什么URLSession超时或由于缺少参数错误而失败?

时间:2018-07-06 04:39:02

标签: swift django django-rest-framework django-socialauth urlsession

我不知道为什么这个URLSession调用超时。

let jsonUrlString = "https://myapp.herokuapp.com/api-auth/invalidate-sessions/"
guard let url = URL(string: jsonUrlString) else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer " + accessToken!, forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let params = ["client_id": djangoAppClientID,]
guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) else { return }
request.httpBody = httpBody

URLSession.shared.dataTask(with: request) { (data, response, err) in
    if let httpResponse = response as? HTTPURLResponse {
        if httpResponse.statusCode == 204 {
            print("Success!")
        } else {
            print("Failure, error = ", err as Any)
        }
    }
}.resume()

服务器立即完成无效会话。这是rest_framework_social_oauth2中的一种方法,我已经用print语句对其进行了检测,以查看它是否达到了我的期望,并返回204状态代码:

2018-07-06T03:52:27.651829+00:00 app[web.1]: 10.11.239.176 - - [05/Jul/2018:20:52:27 -0700] "POST /api-auth/invalidate-sessions/ HTTP/1.1" 204 2 "-“ "myapp/1 CFNetwork/897.15 Darwin/17.6.0"

是的,在客户端(上面的代码),它挂起60秒钟,然后打印:

Failure, error = Optional(Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSUnderlyingError=0x60800005a670 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x60000009fb80 [0x106f80c80]>{length = 16, capacity = 16, bytes = 0x100201bb22caef6d0000000000000000}, _kCFStreamErrorCodeKey=57, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=https://myapp.herokuapp.com/api-auth/invalidate-sessions/, NSErrorFailingURLKey=https://myapp.herokuapp.com/api-auth/invalidate-sessions/, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=57, NSLocalizedDescription=The network connection was lost.})

有什么想法为什么客户没有立即得到我的期望?好像它正在阻塞,正在等待更多数据,但我不知道为什么会这样。

更新

当我删除其中包含“ application / json”的行时,我会很快收到响应,没有超时。但是它说“此字段是必填字段”,指的是“ client_id”。因此很明显,此问题与我制定URLsession请求的方式有关。我试图模拟以下curl命令:

curl -H "Authorization: Bearer <my access token>" -X POST -d "client_id=<my client id>" https://myapp.herokuapp.com/api-auth/invalidate-sessions/

为清楚起见,我发现上面的curl命令有效。当我尝试将其转换为URLSession时,它根本不起作用,尽管我现在已经尝试了十多种方法。它要么立即返回400错误,说明client_id是必需的,要么挂起直到超时。

更新2

卷曲返回运行时,它将立即返回。输出为:

Moe:Server dylan$ curl -v -H "Authorization: Bearer yyyyyyyyyyyyyyy" -X POST -d "client_id=xxxxxxxxxxxxxxxxxxxxxxxxx" https://myapp.herokuapp.com/api-auth/invalidate-sessions/
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 52.20.65.241...
* TCP_NODELAY set
* Connected to myapp.herokuapp.com (52.20.65.241) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=Heroku, Inc.; CN=*.herokuapp.com
*  start date: Apr 19 00:00:00 2017 GMT
*  expire date: Jun 22 12:00:00 2020 GMT
*  subjectAltName: host "myapp.herokuapp.com" matched cert's "*.herokuapp.com"
*  issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
*  SSL certificate verify ok.
 > POST /api-auth/invalidate-sessions/ HTTP/1.1
 > Host: myapp.herokuapp.com
 > User-Agent: curl/7.54.0
 > Accept: */*
 > Authorization: Bearer yyyyyyyyyyyyyyy
 > Content-Length: 50
 > Content-Type: application/x-www-form-urlencoded
 > 
* upload completely sent off: 50 out of 50 bytes
 < HTTP/1.1 204 No Content
 < Connection: keep-alive
 < Server: gunicorn/19.8.1
 < Date: Sat, 07 Jul 2018 02:44:30 GMT
 < Content-Type: application/json
 < Vary: Accept
 < Allow: OPTIONS, POST
 < X-Frame-Options: SAMEORIGIN
 < Content-Length: 2
 < Via: 1.1 vegur
 < 
* Connection #0 to host myapp.herokuapp.com left intact

另一方面,邮递员由于某种原因需要60秒才能返回,但与URLsession不同,它返回状态为204,而不是错误。

Postman screenshot

还有“身体”标签...

Postman body tab open

更新3

这是服务器执行的Django代码。我想知道Postman和URLsession是否挂起(但不会卷曲),因为服务器成功时,它只是返回一个空的Response?

@api_view(['POST'])
@authentication_classes([OAuth2Authentication])
@permission_classes([permissions.IsAuthenticated])
def invalidate_sessions(request):
    client_id = request.data.get("client_id", None)
    if client_id is None:
        return Response({
            "client_id": ["This field is required."]
        }, status=status.HTTP_400_BAD_REQUEST)

    try:
        app = Application.objects.get(client_id=client_id)
    except Application.DoesNotExist:
        return Response({
        "detail": "The application linked to the provided client_id could not be found."
        }, status=status.HTTP_400_BAD_REQUEST)

    tokens = AccessToken.objects.filter(user=request.user, application=app)
    tokens.delete()
    return Response({}, status=status.HTTP_204_NO_CONTENT)

0 个答案:

没有答案