我不知道为什么这个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,而不是错误。
还有“身体”标签...
更新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)