504- Gateway timeout only in django function

Viewed 223

I have a very mind-boggling problem and my team has struggled to solve it. We do have it narrowed down but not 100%.

Introduction

We are trying to implement LTI in a Django app with the Vue frontend. To fetch the token from the URL the backend makes a POST request to the URL with data and should receive a token or error if it's expired or invalid.

Design


Browser ---- POST REQUEST --> view function on Server (Django) --- POST REQUEST --> Auth URL

Problem


The post request that Django view makes times out with 504 Gateway Timeout. This could be normal if the server takes a lot of time. However, increasing the time did not help and checked Auth URL with POSTMAN it worked fine and was not down.

What I have tried


We decided to debug or diagnose this issue that why a code block works in a function when it is called through a shell but not when it is called by a POST request does not.

  1. Eliminated the front end and used POSTMAN to send a POST request to my Django server -- timeout on the Auth URL
  2. Called the same function using Django shell -- worked
  3. Copied the code into a separate python file outside Django -- worked
  4. Used same virtual env for all above

What it appears to be


When a POST function is called and another post request is made inside it then it times out. Please note: If I make a POST request in the same situation with invalid data (say missing grant_type) then it does not time out.


Code Block


auth_request = {
    "grant_type": "client_credentials",
    "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
    "client_assertion": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlJVbzNJWWlSR0ZDYUhNNEg0S2lid095enAtRU9KWlAweXkwd0g3bk5VOEEifQ.eyJpc3MiOiI2NjkxNmZmYy03YjE5LTQ0MWEtYjE5Zi0yOGQxMzVmYjZjOWYiLCJzdWIiOiI2NjkxNmZmYy03YjE5LTQ0MWEtYjE5Zi0yOGQxMzVmYjZjOWYiLCJhdWQiOiJodHRwczovL2RldmVsb3Blci5ibGFja2JvYXJkLmNvbS9hcGkvdjEvZ2F0ZXdheS9vYXV0aDIvand0dG9rZW4iLCJpYXQiOjE2NTMyODcyNzMsImV4cCI6MTY1MzI4NzMzOCwianRpIjoibHRpLXNlcnZpY2UtdG9rZW4tMDQyZTZhNjctNDA2My00YmQ1LWI2NmQtNTM4YjU2ZTllM2Q1In0.8Jaou965cPTCFv-7yP9iIlH8mMgQjAi0AR2li0KwCcRuHsRZ_1OpbE83bZ06RMXhbjA4crRqTI4zMi8aNfq16Mkg4lXoPj8JiJW7q8b_ZQ1rLZvIojmabehYjpyscHRitFPLibfTYF2mCjUyHqwPgnFRLNrHIVuSvM0BiK56PuYK6SiiSjxu2U3bmJqOHNW2mqx2YYfkaXx2u7ru6CKTiL3KBGzFPYjCUwwWNBdbz4R0g0aHK_l-hhA3oi_pCDZOyqdnyCmGAj5SpZbuZOqrZbQBrqPoEFtXdNDPpHGGwW7IUbbmCtsmE2NqQiYt6snmK-1pbxsLxE0mXrpDqASh4A",
    "scope": "https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly",
}
response = requests.post(
    "https://developer.blackboard.com/api/v1/gateway/oauth2/jwttoken",
    data=auth_request,
)
response = response.json()
print(response)
1 Answers

After days of trying to figure it out, we deployed the project with Production settings and it worked. Upon investigation on why it was not working on staging we found the following:

  1. Front end sends a POST request to the back end
  2. Backend then encoded the data using the private key and sent it to a 3rd party server
  3. Because 3rd party server needed to validate our jwks message it sent another request to a URL on our staging server.
  4. This 3rd request was not addressed as the server only had one thread. Adding a threads parameter to gunicorn did the trick

gunicorn ripple.wsgi --reload --log-level debug --threads 4

Related