1717
1818from flask import request
1919from functools import lru_cache
20- from os .path import join
21- from os .path import getmtime
22- from os .path import getsize
20+ from os .path import join , getmtime , getsize
2321from werkzeug .datastructures import Headers
2422
2523
2624class ApiDoc (object ):
25+ """
26+ ApiDoc hosts the apidoc files in a specified url.
27+ """
28+
2729 def __init__ (self , folder_path = None , url_path = None , app = None ):
30+ """
31+ Initializes a new instance of ApiDoc.
32+
33+ :param folder_path: the folder with apidoc files. Defaults to the 'docs' folder in the flask static folder.
34+ :param url_path: the url path for the apidoc files. Defaults to the '/docs'.
35+ :param app: the flask application.
36+ """
37+
2838 self .folder_path = folder_path
2939 self .url_path = url_path
3040
@@ -40,6 +50,11 @@ def __init__(self, folder_path=None, url_path=None, app=None):
4050 self .init_app (app )
4151
4252 def init_app (self , app ):
53+ """
54+ Adds the flask url routes for the apidoc files.
55+ :param app: the flask application.
56+ """
57+
4358 self .app = app
4459
4560 url = self .url_path
@@ -50,36 +65,49 @@ def init_app(self, app):
5065 app .add_url_rule (url , 'docs' , self .__send_static_file , strict_slashes = True )
5166 app .add_url_rule (url + '<path:path>' , 'docs' , self .__send_static_file , strict_slashes = True )
5267
53- @lru_cache ()
54- def __get_project_info (self ):
55- file_name = join (self .app .static_folder , self .folder_path , 'api_project.json' )
56-
57- with open (file_name , 'rt' ) as file :
58- data = file .read ()
59-
60- return json .loads (data )
61-
6268 def __send_static_file (self , path = None ):
69+ """
70+ Sends apidoc files from the apidoc folder to the browser.
71+ :param path: the apidoc file
72+ """
73+
6374 if not path :
6475 path = 'index.html'
6576
6677 file_name = join (self .folder_path , path )
6778
79+ # Both api_project.js and api_data.js have the absolute url
80+ # hard coded so we replace them by the current url.
6881 if path == 'api_project.js' or path == 'api_data.js' :
6982 return self .__send_api_file (file_name )
7083
84+ # Any other apidoc file is treated as a normal static file
7185 return self .app .send_static_file (file_name )
7286
73- @lru_cache (maxsize = 1048576 )
87+ @lru_cache (maxsize = None , typed = True )
7488 def __send_api_file (self , file_name ):
89+ """
90+ Sends apidoc files from the apidoc folder to the browser.
91+ This method replaces all absolute urls in the file by
92+ the current url.
93+ :param file_name: the apidoc file
94+ """
95+
7596 file_name = join (self .app .static_folder , file_name )
7697
7798 with open (file_name , 'rt' ) as file :
7899 data = file .read ()
79100
80- project_info = self .__get_project_info ()
101+ # replaces the hard coded url by the
102+ # current url.
103+ api_project = self .__read_api_project ()
104+
105+ new_url = request .url_root .strip ('/' )
106+ old_url = api_project .get ('url' )
107+ data = data .replace (old_url , new_url )
81108
82- data = self .__replace_url (data , project_info .get ('url' ), request .url_root )
109+ # creates a flask response to send
110+ # the file to the browser
83111
84112 headers = Headers ()
85113 headers ['Content-Length' ] = getsize (file_name )
@@ -93,7 +121,16 @@ def __send_api_file(self, file_name):
93121
94122 return response
95123
96- @staticmethod
97- def __replace_url (data , old_url , new_url ):
98- new_url = new_url .strip ('/' )
99- return data .replace (old_url , new_url )
124+ @lru_cache (maxsize = None )
125+ def __read_api_project (self ):
126+ """
127+ Reads the api_project.json file from apidoc folder as a json string.
128+ :return: a json string
129+ """
130+
131+ file_name = join (self .app .static_folder , self .folder_path , 'api_project.json' )
132+
133+ with open (file_name , 'rt' ) as file :
134+ data = file .read ()
135+
136+ return json .loads (data )
0 commit comments