How to handle HTTP Status Codes across a Python application?
Asked Answered
J

1

5

I'm trying to standardize my handling of HTTP status codes returned from various APIs in an effort to reduce the amount of code I copy across files.

For my current application, I have a set of files that each contain one class that all derive inheritance from one master class. I'm using the Python requests module to consume the APIs.

So far, I've written custom status code handling in each function to continue with a 200, log the request I sent with a 400, log the url for a 404, retry for 5xx, but it's a hassle to keep copying this code across functions and classes.

I'm thinking of the following (note that I've simplified my code here to just use GETs, but in reality, I'm mostly POSTing and receiving back a json response):

apiMaster.py

class ApiMaster(object):
    def _handle_response(self, resp):
        if resp.status_code == 200: # or requests.code.ok
            return resp.json()
        if resp.status_code == 400:
            err_msg = "400 Error - Bad Request\n" + resp.request.url + "\n" + resp.request.data
            raise HTTPError(err_msg)
        ...

apiA.py

class Api_A(ApiMaster):
    def query_json_a(self):
        resp = requests.get(self.url + '/a.json')
        try:
            resp_json = self._handle_response(resp)
        except HTTPError as e:
            logger.error(str(e))

apiB.py

class Api_B(ApiMaster):
    def query_json_b(self):
        # same as API A but with different endpoints and purpose

However, this still seems iffy. I don't know if it's reasonable to try to account for every status code returned by an API. And this would also require me to copy this code to any new project I start working on.

Is there a better way to do this?

Josefina answered 18/1, 2018 at 16:30 Comment(0)
O
9

Your solution seems good, you can further it by moving more stuff into the shared method, e.g.

class ApiMaster(object):

    def make_request(self, url, method, query_params=None, body=None, logger=None):
        if not logger:
            get_default_logger_somehow()

        response = requests.request(method, url, params=query_params, json=body)
        if response.status_code == 400:
            logger.error(response.request.url)
        elif response.status_code == 200:
            try:
                return reponse.json()
            except SomeError:
                return None

class Api1(ApiMaster):
    json = self.make_request('post', 'http://example/com')
Orella answered 18/1, 2018 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.