tina4-python 0.2.22__tar.gz → 0.2.25__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. {tina4_python-0.2.22 → tina4_python-0.2.25}/PKG-INFO +1 -1
  2. {tina4_python-0.2.22 → tina4_python-0.2.25}/pyproject.toml +1 -1
  3. tina4_python-0.2.25/tina4_python/.env +7 -0
  4. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Debug.py +2 -1
  5. tina4_python-0.2.25/tina4_python/MiddleWare.py +71 -0
  6. tina4_python-0.2.25/tina4_python/Request.py +18 -0
  7. tina4_python-0.2.25/tina4_python/Response.py +96 -0
  8. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Router.py +89 -29
  9. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Webserver.py +1 -1
  10. tina4_python-0.2.25/tina4_python/logs/debug.log +1066 -0
  11. tina4_python-0.2.25/tina4_python/secrets/domain.cert +21 -0
  12. tina4_python-0.2.25/tina4_python/secrets/private.key +30 -0
  13. tina4_python-0.2.25/tina4_python/secrets/public.key +9 -0
  14. tina4_python-0.2.25/tina4_python/test.db +0 -0
  15. tina4_python-0.2.22/tina4_python/Request.py +0 -25
  16. tina4_python-0.2.22/tina4_python/Response.py +0 -77
  17. {tina4_python-0.2.22 → tina4_python-0.2.25}/README.md +0 -0
  18. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Auth.py +0 -0
  19. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Constant.py +0 -0
  20. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Database.py +0 -0
  21. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/DatabaseResult.py +0 -0
  22. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Env.py +0 -0
  23. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Localization.py +0 -0
  24. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Messages.py +0 -0
  25. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Migration.py +0 -0
  26. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Session.py +0 -0
  27. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/ShellColors.py +0 -0
  28. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Swagger.py +0 -0
  29. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/Template.py +0 -0
  30. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/__init__.py +0 -0
  31. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/messages.pot +0 -0
  32. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/css/readme.md +0 -0
  33. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/favicon.ico +0 -0
  34. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/images/403.png +0 -0
  35. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/images/404.png +0 -0
  36. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/images/logo.png +0 -0
  37. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/images/readme.md +0 -0
  38. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/js/readme.md +0 -0
  39. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/js/tina4helper.js +0 -0
  40. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/swagger/index.html +0 -0
  41. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
  42. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/templates/errors/403.twig +0 -0
  43. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/templates/errors/404.twig +0 -0
  44. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/templates/readme.md +0 -0
  45. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
  46. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
  47. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
  48. {tina4_python-0.2.22 → tina4_python-0.2.25}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tina4-python
3
- Version: 0.2.22
3
+ Version: 0.2.25
4
4
  Summary: Tina4Python - This is not another framework for Python
5
5
  Author: Andre van Zuydam
6
6
  Author-email: andrevanzuydam@gmail.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "tina4-python"
3
- version = "0.2.22"
3
+ version = "0.2.25"
4
4
  description = "Tina4Python - This is not another framework for Python"
5
5
  authors = ["Andre van Zuydam <andrevanzuydam@gmail.com>"]
6
6
  readme = "README.md"
@@ -0,0 +1,7 @@
1
+ # Project Settings
2
+ PROJECT_NAME="My Project"
3
+ VERSION=1.0.0
4
+ TINA4_LANGUAGE=en
5
+ TINA4_SECRET=ABCDEF
6
+ TINA4_DEBUG_LEVEL=[TINA4_LOG_ALL]
7
+ API_KEY=f9ca99e18c7bce9c6852df4257a3280b
@@ -66,7 +66,8 @@ class Debug:
66
66
  print(output, "", end="")
67
67
  print()
68
68
 
69
- sys.stdout.flush()
69
+ if sys.stdout is not None:
70
+ sys.stdout.flush()
70
71
 
71
72
  handler.flush()
72
73
  logger.removeHandler(handler)
@@ -0,0 +1,71 @@
1
+
2
+
3
+ class MiddleWare:
4
+ def __init__(self, middleware_class):
5
+ """
6
+
7
+ :param middleware_class:
8
+ """
9
+ self.before_methods = []
10
+ self.after_methods = []
11
+ self.any_methods = []
12
+ self.middleware_class = middleware_class
13
+
14
+ self.methods_list = [method for method in vars(middleware_class) if callable(
15
+ getattr(middleware_class, method)) and not method.startswith("__")]
16
+
17
+ for method in self.methods_list:
18
+ if method.startswith("before"):
19
+ self.before_methods.append(method)
20
+ elif method.startswith("after"):
21
+ self.after_methods.append(method)
22
+ else:
23
+ self.any_methods.append(method)
24
+
25
+ def call_before_methods(self, request, response):
26
+ """
27
+ Call before methods
28
+ :param request:
29
+ :param response:
30
+ :return:
31
+ """
32
+ for method in self.before_methods:
33
+ method = getattr(self.middleware_class, method)
34
+ request, response = method(request, response)
35
+ return request, response
36
+
37
+ def call_after_methods(self, request, response):
38
+ """
39
+ Call after methods
40
+ :param request:
41
+ :param response:
42
+ :return:
43
+ """
44
+ for method in self.after_methods:
45
+ method = getattr(self.middleware_class, method)
46
+ request, response = method(request, response)
47
+ return request, response
48
+
49
+ def call_any_methods(self, request, response):
50
+ """
51
+ Call any methods
52
+ :param request:
53
+ :param response:
54
+ :return:
55
+ """
56
+ for method in self.any_methods:
57
+ method = getattr(self.middleware_class, method)
58
+ request, response = method(request, response)
59
+ return request, response
60
+
61
+ def call_direct_method(self, request, response, method_name):
62
+ """
63
+ Call direct methods
64
+ :param request:
65
+ :param response:
66
+ :param method_name:
67
+ :return:
68
+ """
69
+ method = getattr(self.middleware_class, method_name)
70
+ request, response = method(request, response)
71
+ return request, response
@@ -0,0 +1,18 @@
1
+ #
2
+ # Tina4 - This is not a 4ramework.
3
+ # Copy-right 2007 - current Tina4
4
+ # License: MIT https://opensource.org/licenses/MIT
5
+ #
6
+ # flake8: noqa: E501
7
+ import inspect
8
+
9
+ request = None
10
+ body = None
11
+ params = {}
12
+ headers = {}
13
+ cookies = {}
14
+ url = None
15
+ session = None
16
+ files = {}
17
+ raw_data = None
18
+ raw_content = None
@@ -0,0 +1,96 @@
1
+ #
2
+ # Tina4 - This is not a 4ramework.
3
+ # Copy-right 2007 - current Tina4
4
+ # License: MIT https://opensource.org/licenses/MIT
5
+ #
6
+ # flake8: noqa: E501
7
+ import json
8
+ import inspect
9
+ from types import ModuleType
10
+
11
+ from markdown_it.common.utils import isStrSpace
12
+
13
+ from tina4_python import Constant
14
+ from tina4_python import DatabaseResult
15
+ from tina4_python.Debug import Debug
16
+
17
+ headers = {}
18
+ content = ""
19
+ http_code = Constant.HTTP_OK
20
+ content_type = Constant.TEXT_HTML
21
+
22
+
23
+ class Response:
24
+ def __init__(self, content_in=None, http_code_in=None, content_type_in=None,
25
+ headers_in=None):
26
+ global headers
27
+ global content
28
+ global http_code
29
+ global content_type
30
+
31
+ if (not isinstance(content_in, bool) and not isinstance(content_in, object)
32
+ and not isinstance(content_in, bytes)
33
+ and not isinstance(content_in, str)
34
+ and not isinstance(content_in, list) and inspect.isclass(type(content_in))):
35
+ content_in = dict(content_in)
36
+
37
+ # check if database result
38
+ if type(content_in) is DatabaseResult.DatabaseResult:
39
+ content_type = Constant.APPLICATION_JSON
40
+ content_in = content_in.to_json()
41
+
42
+ # convert the dictionary or list into JSON
43
+ if not isinstance(content_in, bool) and type(content_in) is dict or type(content_in) is list:
44
+ content_in = json.dumps(content_in)
45
+ content_type = Constant.APPLICATION_JSON
46
+
47
+ if isinstance(content_in, bool):
48
+ if content_in:
49
+ content_in = "True"
50
+ else:
51
+ content_in = "False"
52
+
53
+ if isinstance(content_in, ModuleType):
54
+ content_in = json.dumps({"error": "Cannot decode object of type " + str(type(content_in))})
55
+ content_type = Constant.APPLICATION_JSON
56
+
57
+ if content is not None and isinstance(content_in, str):
58
+ content_in = content + content_in
59
+
60
+ self.headers = headers_in if headers_in is not None else headers
61
+ self.content = content_in if content_in is not None else content
62
+ self.http_code = http_code_in if http_code_in is not None else http_code
63
+ self.content_type = content_type_in if content_type_in is not None else content_type
64
+ headers = self.headers
65
+ http_code = self.http_code
66
+ content_type = self.content_type
67
+ content = self.content
68
+
69
+ @staticmethod
70
+ def redirect(redirect_url):
71
+ """
72
+ Redirects a request to redirect_url
73
+ :param redirect_url:
74
+ :return:
75
+ """
76
+ global headers
77
+ global content
78
+ global http_code
79
+ global content_type
80
+ headers = {}
81
+ http_code = Constant.HTTP_REDIRECT
82
+ headers["Location"] = redirect_url
83
+ content = ""
84
+ content_type = Constant.TEXT_HTML
85
+ return Response("", http_code, content_type, headers)
86
+
87
+ @staticmethod
88
+ def add_header(key, value):
89
+ """
90
+ Adds a header for the response
91
+ :param key:
92
+ :param value:
93
+ :return:
94
+ """
95
+ global headers
96
+ headers[key] = value
@@ -13,9 +13,10 @@ import io
13
13
  import tina4_python
14
14
  from tina4_python import Constant
15
15
  from tina4_python.Debug import Debug
16
+ from tina4_python import Response
16
17
  from tina4_python import Request
17
- from tina4_python.Response import Response
18
18
  from tina4_python.Template import Template
19
+ from tina4_python.MiddleWare import MiddleWare
19
20
 
20
21
 
21
22
  class Router:
@@ -59,18 +60,28 @@ class Router:
59
60
  # Renders the URL and returns the content
60
61
  @staticmethod
61
62
  async def get_result(url, method, request, headers, session):
63
+ global Request
64
+ global Response
65
+
66
+ Response.headers = {}
67
+ Response.content = ""
68
+ Response.http_code = Constant.HTTP_OK
69
+ Response.content_type = Constant.TEXT_HTML
70
+ result = None
71
+
62
72
  Debug("Root Path " + tina4_python.root_path + " " + url, method, Constant.TINA4_LOG_DEBUG)
63
73
  tina4_python.tina4_current_request["url"] = url
64
74
  tina4_python.tina4_current_request["headers"] = headers
65
75
 
66
76
  # we can add other methods later but right now we validate posts
67
- if method in [Constant.TINA4_GET, Constant.TINA4_POST, Constant.TINA4_PUT, Constant.TINA4_PATCH, Constant.TINA4_DELETE]:
77
+ if method in [Constant.TINA4_GET, Constant.TINA4_POST, Constant.TINA4_PUT, Constant.TINA4_PATCH,
78
+ Constant.TINA4_DELETE]:
68
79
  content_type = "text/html"
69
80
  if "content-type" in headers:
70
81
  content_type = headers["content-type"]
71
82
 
72
83
  if content_type == "application/json":
73
- content = {"error": "403 - Forbidden", "data": {"server": {"url": url}}};
84
+ content = {"error": "403 - Forbidden", "data": {"server": {"url": url}}}
74
85
  else:
75
86
  content = Template.render_twig_template(
76
87
  "errors/403.twig", {"server": {"url": url}})
@@ -93,14 +104,11 @@ class Router:
93
104
  validated = True
94
105
 
95
106
  if not validated and method != Constant.TINA4_GET:
96
- return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML)
107
+ return Response.Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML)
97
108
  else:
98
109
  if request["body"] is not None and "formToken" in request["body"]:
99
110
  del request["body"]["formToken"]
100
111
 
101
- # default response
102
- result = Response("", Constant.HTTP_NOT_FOUND, Constant.TEXT_HTML)
103
-
104
112
  # split URL and extract query string
105
113
  url_parts = url.split('?')
106
114
  url = url_parts[0]
@@ -111,23 +119,25 @@ class Router:
111
119
  if os.path.isfile(static_file):
112
120
  mime_type = mimetypes.guess_type(url)[0]
113
121
  with open(static_file, 'rb') as file:
114
- return Response(file.read(), Constant.HTTP_OK, mime_type)
122
+ return Response.Response(file.read(), Constant.HTTP_OK, mime_type)
115
123
 
116
124
  old_stdout = None
125
+ buffer = io.StringIO()
117
126
  for route in tina4_python.tina4_routes.values():
118
127
  if route["method"] != method:
119
128
  continue
120
129
  Debug("Matching route " + route['route'] + " to " + url, Constant.TINA4_LOG_DEBUG)
121
130
  if Router.match(url, route['route']):
122
- if "swagger" in route and route["swagger"] is not None and "secure" in route["swagger"]:
131
+ if "swagger" in route and route["swagger"] is not None and "secure" in route["swagger"]:
123
132
  if route["swagger"]["secure"] and not validated:
124
- return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML)
133
+ return Response.Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML)
125
134
 
126
135
  router_response = route["callback"]
127
136
 
128
137
  # Add the inline variables & construct a Request variable
129
138
  request["params"].update(Router.variables)
130
139
 
140
+
131
141
  Request.request = request # Add the request object
132
142
  Request.headers = headers # Add the headers
133
143
  Request.params = request["params"]
@@ -140,31 +150,56 @@ class Router:
140
150
 
141
151
  tina4_python.tina4_current_request = Request
142
152
 
143
- old_stdout = sys.stdout # Memorize the default stdout stream
153
+ old_stdout = sys.stdout # Memorize the default stdout stream
144
154
  sys.stdout = buffer = io.StringIO()
145
- result = await router_response(request=Request, response=Response)
146
155
 
147
- if "cache" in route and route["cache"] is not None:
148
- if not route["cache"]["cached"]:
149
- result.headers["Cache-Control"] = "max-age=1, must-revalidate"
150
- result.headers["Pragma"] = "no-cache"
151
- result.headers["Clear-Site-Data"] = "cache"
156
+ if "middleware" in route:
157
+ middleware_runner = MiddleWare(route["middleware"]["class"])
158
+
159
+ if "methods" in route["middleware"]:
160
+ for method in route["middleware"]["methods"]:
161
+ Request, Response = middleware_runner.call_direct_method(Request, Response, method)
152
162
  else:
153
- result.headers["Cache-Control"] = "max-age="+str(route["cache"]["max_age"])+", must-revalidate"
154
- result.headers["Pragma"] = "cache"
155
- else:
156
- result.headers["Cache-Control"] = "max-age=-1, must-revalidate"
157
- result.headers["Pragma"] = "cache"
163
+ Request, Response = middleware_runner.call_before_methods(Request, Response)
164
+ Request, Response = middleware_runner.call_any_methods(Request, Response)
165
+
166
+ result = await router_response(request=Request, response=Response.Response)
167
+
168
+ if "middleware" in route:
169
+ middleware_runner = MiddleWare(route["middleware"]["class"])
158
170
 
171
+ if "methods" in route["middleware"]:
172
+ for method in route["middleware"]["methods"]:
173
+ Request, result = middleware_runner.call_direct_method(Request, result, method)
174
+ else:
175
+ Request, result = middleware_runner.call_after_methods(Request, result)
176
+ Request, result = middleware_runner.call_any_methods(Request, result)
177
+
178
+ if result is not None:
179
+ if "cache" in route and route["cache"] is not None:
180
+ if not route["cache"]["cached"]:
181
+ result.headers["Cache-Control"] = "max-age=1, must-revalidate"
182
+ result.headers["Pragma"] = "no-cache"
183
+ else:
184
+ result.headers["Cache-Control"] = "max-age=" + str(
185
+ route["cache"]["max_age"]) + ", must-revalidate"
186
+ result.headers["Pragma"] = "cache"
187
+ else:
188
+ result.headers["Cache-Control"] = "max-age=-1, must-revalidate"
189
+ result.headers["Pragma"] = "cache"
159
190
 
160
191
  break
161
192
 
162
193
  if result is None:
163
- sys.stdout = old_stdout
194
+ if old_stdout is not None:
195
+ sys.stdout = old_stdout
196
+ else:
197
+ sys.stdout = buffer = io.StringIO()
198
+
164
199
  try:
165
- return Response(json.loads(buffer.getvalue()), Constant.HTTP_OK, Constant.APPLICATION_JSON)
200
+ return Response.Response(json.loads(buffer.getvalue()), Constant.HTTP_OK, Constant.APPLICATION_JSON)
166
201
  except:
167
- return Response(buffer.getvalue(), Constant.HTTP_OK, Constant.TEXT_HTML)
202
+ return Response.Response(buffer.getvalue(), Constant.HTTP_OK, Constant.TEXT_HTML)
168
203
 
169
204
  # If no route is matched, serve 404
170
205
  if result.http_code == Constant.HTTP_NOT_FOUND:
@@ -184,12 +219,12 @@ class Router:
184
219
  result.headers["Pragma"] = "no-cache"
185
220
  content = Template.render_twig_template(twig_file, {"request": tina4_python.tina4_current_request})
186
221
  if content != "":
187
- return Response(content, Constant.HTTP_OK, Constant.TEXT_HTML, result.headers)
222
+ return Response.Response(content, Constant.HTTP_OK, Constant.TEXT_HTML, result.headers)
188
223
 
189
224
  if result.http_code == Constant.HTTP_NOT_FOUND:
190
225
  content = Template.render_twig_template(
191
226
  "errors/404.twig", {"server": {"url": url}})
192
- return Response(content, Constant.HTTP_NOT_FOUND, Constant.TEXT_HTML)
227
+ return Response.Response(content, Constant.HTTP_NOT_FOUND, Constant.TEXT_HTML)
193
228
 
194
229
  return result
195
230
 
@@ -209,7 +244,8 @@ class Router:
209
244
  def add(method, route, callback):
210
245
  Debug("Adding a route: " + route, Constant.TINA4_LOG_DEBUG)
211
246
  if not callback in tina4_python.tina4_routes:
212
- tina4_python.tina4_routes[callback] = {"route": route, "callback": callback, "method": method, "swagger": None, "cached": False}
247
+ tina4_python.tina4_routes[callback] = {"route": route, "callback": callback, "method": method,
248
+ "swagger": None, "cached": False}
213
249
  else:
214
250
  tina4_python.tina4_routes[callback]["route"] = route
215
251
  tina4_python.tina4_routes[callback]["callback"] = callback
@@ -227,6 +263,7 @@ def get(path: str):
227
263
  :param arguments:
228
264
  :return:
229
265
  """
266
+
230
267
  def actual_get(callback):
231
268
  route_paths = path.split('|')
232
269
  for route_path in route_paths:
@@ -242,6 +279,7 @@ def post(path):
242
279
  :param path:
243
280
  :return:
244
281
  """
282
+
245
283
  def actual_post(callback):
246
284
  route_paths = path.split('|')
247
285
  for route_path in route_paths:
@@ -257,6 +295,7 @@ def put(path):
257
295
  :param path:
258
296
  :return:
259
297
  """
298
+
260
299
  def actual_put(callback):
261
300
  route_paths = path.split('|')
262
301
  for route_path in route_paths:
@@ -272,6 +311,7 @@ def patch(path):
272
311
  :param path:
273
312
  :return:
274
313
  """
314
+
275
315
  def actual_patch(callback):
276
316
  route_paths = path.split('|')
277
317
  for route_path in route_paths:
@@ -287,6 +327,7 @@ def delete(path):
287
327
  :param path:
288
328
  :return:
289
329
  """
330
+
290
331
  def actual_delete(callback):
291
332
  route_paths = path.split('|')
292
333
  for route_path in route_paths:
@@ -295,6 +336,7 @@ def delete(path):
295
336
 
296
337
  return actual_delete
297
338
 
339
+
298
340
  def cached(is_cached, max_age=60):
299
341
  """
300
342
  Sets whether the route is cached or not
@@ -302,10 +344,28 @@ def cached(is_cached, max_age=60):
302
344
  :param max_age:
303
345
  :return:
304
346
  """
347
+
305
348
  def actual_cached(callback):
306
349
  if callback not in tina4_python.tina4_routes:
307
350
  tina4_python.tina4_routes[callback] = {}
308
351
  tina4_python.tina4_routes[callback]["cache"] = {"cached": is_cached, "max_age": max_age}
309
352
  return callback
310
353
 
311
- return actual_cached
354
+ return actual_cached
355
+
356
+
357
+ def middleware(middleware, specific_methods=[]):
358
+ """
359
+ Sets middleware for the route and methods that need to be called
360
+ :param middleware:
361
+ :param specific_methods:
362
+ :return:
363
+ """
364
+
365
+ def actual_middleware(callback):
366
+ if callback not in tina4_python.tina4_routes:
367
+ tina4_python.tina4_routes[callback] = {}
368
+ tina4_python.tina4_routes[callback]["middleware"] = {"class": middleware, "methods": specific_methods}
369
+ return callback
370
+
371
+ return actual_middleware
@@ -125,7 +125,7 @@ class Webserver:
125
125
  "Origin, X-Requested-With, Content-Type, Accept, Authorization", headers)
126
126
  self.send_header("Access-Control-Allow-Credentials", "True", headers)
127
127
  self.send_header("Content-Type", response.content_type, headers)
128
- self.send_header("Content-Length", str(len(response.content)), headers)
128
+ # self.send_header("Content-Length", str(len(response.content)), headers)
129
129
  self.send_header("Connection", "Keep-Alive", headers)
130
130
  self.send_header("Keep-Alive", "timeout=5, max=30", headers)
131
131