pyopenapi/pyswagger

Accept a urllib.requests.Request instead of a string in App.load

multimeric opened this issue · 2 comments

App.load() assumes that url is a string, for requesting the OpenAPI.json:

:param str url: url of path of Swagger API definition

However, these are cases where we need more configurability. For example, I've just encountered an OpenAPI endpoint that rejects the urllib UserAgent, so I would like to be able to provide a customised UserAgent via a Request instance, rather than simply a string.

This would be a great help. There are providers such as CloudFlare which explicitly block Python urllib requests; without the ability to pick a new UserAgent pyswagger cannot fetch the swagger file from these.

Hi there!

I had the same problem. What I did as a workaround was subclassing App (which in turn would load a subclassed UrlGetter) and subclass Client.

import six
from pyswagger import App, Security
from pyswagger.getter import UrlGetter
from pyswagger.contrib.client.requests import Client

header_dict = {"User-agent": "Best Alpha Agent/0.0.1a"}

def _url_load(path):
    # original _url_load method is here:
    # https://github.com/pyopenapi/pyswagger/blob/333c4ca08e758cd2194943d9904a3eda3fe43977/pyswagger/getter.py#L141
    ret = f = None
    try:
        # This is new. create a Request object instead of path
        req = six.moves.urllib.request.Request(path, headers=header_dict)
        f = six.moves.urllib.request.urlopen(req)
        ret = f.read()
    finally:
        if f:
            f.close()

    return ret

class CustomUrlGetter(UrlGetter):
    __simple_getter_callback__ = _url_load

class CustomApp(App):
    def load_obj(self, jref, getter=None, parser=None):
        return super(CustomApp, self).load_obj(jref, getter=CustomUrlGetter, parser=parser)

class CustomClient(Client):
    def request(self, req_and_resp, opt=None, headers=None):
        return super(CustomClient, self).request(req_and_resp, opt, headers=header_dict)

Then I do

self.app = CustomApp._create_("https://example.com/swagger.json")
self.auth = Security(self.app)
self.auth.update_with("Basic", ("hello", "isItMeYoureLookingFor"))
self.client = CustomClient(self.auth)

resp = self.client.request(self.app.op["grabbing-from-swagger"](data=data))

Maybe this could help anyone facing the same issue. I hope I helped