How to cache authentication in a python API - python

Our python Api has a structure where consumers will call our main api which will call many apis internally to get data. Since we are calling around 5-8 apis internally depending on the consumer needs, the response time is more than 1 second. We verified the flow and figured out that the authentication step in each internal api is taking longer time and hence bumping up the response time. Do we have any dependencies we can add to cache the authentication so that we dont need to authenticate for each internal api?

Related

Concurrency with a REST API that uses JWT

I am designing a solution that will perform concurrent http requests to certain REST API. Thing is that this API requires to make a POST request to an authentication endpoint (with username + api_key in the header) so that the server gives you a 20min valid JWT.
As far as I see whenever you ask for a new token, previous token is no longer valid.
In this scenario, is concurrency a possibility? (e.g. using multi-thread in python). As far as I understand, with that principle of working with JWT only one thread shall be doing the job, and not "n" number of threads concurrently, as each thread would invalidate previous token
Create one thread which only manages the authentication, ie fetches a new JWT every 15 minutes (something under 20).
Create N worker threads which make the POST requests.
All threads should share a variable holding the JWT in use and a synchronization primitive like threading.Event. Where you want to store them (global, class, etc) is up to you.
The workers wait for this Event to be set via ev.wait() before every POST request.
The auth thread clear the event via ev.clear() when it needs to fetch a new JWT and when it has set the JWT variable, just set the Event again via ev.set()
This way the POST workers will run freely until the time to refresh the JWT, then pause only while a new one is being fetched.
This can also be done with asyncio.Event if you use async concurrency.

Performance testing with Locust with mocking 3rd party API

I came across an issue with performance testing of payments-related endpoints.
Basically I want to test some endpoints that make request themselves to a 3rd-party providers' API.
Is it possible from Locust's tests level to mock those 3rd-party API for the endpoints I intend to actually test (so without interference with the tested endpoints)?
If I understand correctly, you have a service you'd like to load/performance test but that service calls out to a third-party. But when you do your testing, you don't want to actually make any calls to the third-party service?
Locust is used for simulating client behavior. You can define that client behavior to be whatever you want; typically it's primary use case is for making http calls but almost any task can be done.
If it's your client that makes a request to your service and then makes a separate request to the other third-party service for payment processing, yes, you could define some sort of mocking behavior in Locust to make a real call to your service and then mock out a payment call. But if it's your service that takes a client call and then makes its own call to the third-party payment service, no, Locust can't do anything about that.
For that scenario, you'd be best off making your own simple mock/proxy service of the third-party service. It would take a request from your service, do basic validation to ensure things are coming in as expected, and then just return some canned response that looks like what your service would expect from the third-party. But this would be something you'd have to host yourself and have a method of telling your service to point to this mock service instead (DNS setting, environment variable, etc.). Then you could use Locust to simulate your client behavior as normal and you can test your service in an isolated manner without making any actual calls to the third-party service.
I actually skipped the most important part of the issue, namely I am testing the endpoints from outside of the repo containing them (basically my load test repo calls my app repo). I ended up mocking the provider inside of the app repo, which I initially intended to avoid but turned out to be only reasonable solution at the moment.

What is a good way to not create multiple requests to an API caching the result, if the requests are close in time?

I have a Python webapp, and it's an intermediary service that requests data from another API and caches the data.
The thing is, each requests to the external API requires some paperwork so we better cache that in our side.
Supposing I have two requests to my service, at times T and T + 1 and the API takes 3 seconds to respond, both requests will check that I don't have the result stored and then will try to request to the external API.
What are good mechanisms in Python to do some kind of semaphore until the first requests finishes, then the second request can read from the cache?

Google Task Queue REST pull returning 500 occasionally

I have Python a process leasing tasks from the Google TaskQueue REST API every second in the unlimited loop:
credentials = GoogleCredentials.get_application_default()
task_api = googleapiclient.discovery.build('taskqueue', 'v1beta2', credentials=credentials)
while True:
tasks = task_api.tasks().lease(...).execute()
time.sleep(1)
The process sometimes run well for hours. But occasionally crashes often by one of HTTP error:
500 Backend Error
503 Backend Error
500 An internal error happened in the backend
The process is running on the Google Computing Engine server. It uses a service account key, specified by the GOOGLE_APPLICATION_CREDENTIALS env variable. Is this a Google Task Queue bug or do I miss something? E.g. do I need to reread the credentials before every lease request?
Since the #DalmTo has just answered in comments, I sum up his answers and add the Python solution.
The Google 5xx backed error is flood protection and Google recommends to implement exponential backoff. Despite the link points to Google Drive API, the Google errors are system wide for all the APIs (GAE including). It rarely takes more then 6 retries for it to kick in and respond.
After digging the googleapiclient sources, I've found that the exponential backoff is already implemented in this library, so the solution is dead simple:
tasks = task_api.tasks().lease(...).execute(num_retries=6)
The sources of the http.py::_should_retry_response() shows, that beside HTTP 5xx errors the request is repeated also when the JSON response contains userRateLimitExceeded or rateLimitExceeded error.

Is it possible to use the Spotify Web API to write a desktop application without a callback URI?

I would like to write a simple desktop application for personal use that uses the Spotify Web API to build playlists.
As far as I can tell, however, there's no way to use the API without providing a callback URI, which I don't have, seeing as I don't have a domain or server of any kind (other than my personal computer).
Is there a way to use the API without a URI?
If not, what is the best way to set up a callback URI? I don't have much of any experience working with web applications or client / server stuff, and the APIs I've used in the past haven't required any kind of callback.
Some background first, this answer became a bit longer than what I anticipated.
You need an access token. There are three ways to retrieve an access token; Authentication Code flow, Client Credentials flow, and Implicit Grant flow. These are all part of the oAuth 2.0 specification, each with its own purpose.
Since you're going to modify a user's account, you need that user's permission. Now, if you didn't do any actions that required user permissions, you could've used the Client Credentials flow. That's probably the easiest flow to learn since it just requires a request from your server to Spotify's server, and the response contains an access token. No callback/redirect URI is necessary.
As I'm sure you've read, the Authentication Code flow and Implicit Grant flow both require a callback URI. This is because a flow that includes a user, and the callback URI is where Spotify redirects the user after they have entered their password on Spotify's site.
The Authentication Code flow and Implicit Grant flow has benefits and drawbacks. Access tokens retrieved through the Authentication Code flow can be refreshed, but both return tokens that are valid for one hour. This means that a user that's authenticating using the Implicit Grant flow must reauthenticate after an hour. However, the Authentication Code flow does require some backend work, since it needs to make a request to exchange a code given from Spotify's server for an access token. The Implicit Grant flow is more straight forward - you get the access token and off you go.
The callback URI can be a localhost address, so if your desktop application would spin up a web server locally you could handle the callback on the same machine that the application is running on. (It's probably a good idea to not run the web server on port 80 since that might be used by something else.)
There's skeleton code for each of this authentication flows available on Github, see web-api-auth-examples. Read more about the flows in our Authorization Guide. If you choose to run a web server on the user's machine, I recommend that you use the Implicit Grant flow since that doesn't include any server-to-server requests, so you won't have to expose your client_secret exposed in the code. (As opposed to the Authorization Code flow.)
Also, since you're coding in Python, I recommend that you have a look at spotipy, a wrapper around the Web API packed with convenient methods that'll save you some time. If you do go ahead with the Implicit Grant flow, you should have a look at spotify-web-api-js, which has a similar purpose. Note that these wrappers are not at all required to work with the Web API but they'll make your life easier.

Categories