Ver código fonte

Merge pull request #472 from anandpdoshi/develop

Refactored handler, catch exceptions, response codes
version-14
Anand Doshi 11 anos atrás
pai
commit
38f9636e45
19 arquivos alterados com 311 adições e 268 exclusões
  1. +1
    -18
      frappe/__init__.py
  2. +48
    -55
      frappe/api.py
  3. +54
    -37
      frappe/app.py
  4. +42
    -35
      frappe/auth.py
  5. +7
    -1
      frappe/core/doctype/doctype/doctype.py
  6. +2
    -2
      frappe/core/doctype/doctype/doctype_template.py
  7. +35
    -0
      frappe/exceptions.py
  8. +3
    -28
      frappe/handler.py
  9. +1
    -1
      frappe/hooks.txt
  10. +5
    -0
      frappe/modules/patch_handler.py
  11. BIN
      frappe/public/images/ui/field.jpg
  12. BIN
      frappe/public/images/ui/random-polygons.jpg
  13. BIN
      frappe/public/images/ui/wallpaper.jpg
  14. +3
    -3
      frappe/public/js/frappe/misc/user.js
  15. +1
    -4
      frappe/sessions.py
  16. +5
    -1
      frappe/templates/includes/login.js
  17. +1
    -1
      frappe/templates/pages/login.py
  18. +88
    -68
      frappe/utils/response.py
  19. +15
    -14
      frappe/website/render.py

+ 1
- 18
frappe/__init__.py Ver arquivo

@@ -16,6 +16,7 @@ import json
import semantic_version

from frappe.core.doctype.print_format.print_format import get_html as get_print_html
from .exceptions import *

local = Local()

@@ -71,7 +72,6 @@ form = form_dict = local("form_dict")
request = local("request")
request_method = local("request_method")
response = local("response")
_response = local("_response")
session = local("session")
user = local("user")
flags = local("flags")
@@ -149,21 +149,6 @@ def cache():
_memc = MClient(['localhost:11211'])
return _memc

class DuplicateEntryError(Exception): pass
class ValidationError(Exception): pass
class AuthenticationError(Exception): pass
class PermissionError(Exception): pass
class DataError(Exception): pass
class UnknownDomainError(Exception): pass
class SessionStopped(Exception): pass
class MappingMismatchError(ValidationError): pass
class InvalidStatusError(ValidationError): pass
class DoesNotExistError(ValidationError): pass
class MandatoryError(ValidationError): pass
class InvalidSignatureError(ValidationError): pass
class RateLimitExceededError(ValidationError): pass
class OutgoingEmailError(Exception): pass
def get_traceback():
import utils
return utils.get_traceback()
@@ -562,8 +547,6 @@ def repsond_as_web_page(title, html):
local.response['type'] = 'page'
local.response['page_name'] = 'message.html'
return obj

def build_match_conditions(doctype, as_condition=True):
import frappe.widgets.reportview
return frappe.widgets.reportview.build_match_conditions(doctype, as_condition)


+ 48
- 55
frappe/api.py Ver arquivo

@@ -5,7 +5,7 @@ import frappe
import frappe.handler
import frappe.client
import frappe.widgets.reportview
from frappe.utils.response import build_response, report_error
from frappe.utils.response import build_response

def handle():
"""
@@ -35,63 +35,56 @@ def handle():
if len(parts) > 3:
name = parts[3]
try:
if call=="method":
frappe.local.form_dict.cmd = doctype
frappe.handler.handle()
return
elif call=="resource":
if "run_method" in frappe.local.form_dict:
bean = frappe.bean(doctype, name)
if call=="method":
frappe.local.form_dict.cmd = doctype
return frappe.handler.handle()
elif call=="resource":
if "run_method" in frappe.local.form_dict:
bean = frappe.bean(doctype, name)

if frappe.local.request.method=="GET":
if not bean.has_permission("read"):
frappe.throw("No Permission", frappe.PermissionError)
bean.run_method(frappe.local.form_dict.run_method, **frappe.local.form_dict)
if frappe.local.request.method=="POST":
if not bean.has_permission("write"):
frappe.throw("No Permission", frappe.PermissionError)
bean.run_method(frappe.local.form_dict.run_method, **frappe.local.form_dict)
frappe.db.commit()

else:
if name:
if frappe.local.request.method=="GET":
if not bean.has_permission("read"):
frappe.throw("No Permission", frappe.PermissionError)
bean.run_method(frappe.local.form_dict.run_method, **frappe.local.form_dict)
frappe.local.response.update({
"doclist": frappe.client.get(doctype,
name)})
if frappe.local.request.method=="POST":
if not bean.has_permission("write"):
frappe.throw("No Permission", frappe.PermissionError)
bean.run_method(frappe.local.form_dict.run_method, **frappe.local.form_dict)
frappe.local.response.update({
"doclist": frappe.client.insert(frappe.local.form_dict.doclist)})
frappe.db.commit()

else:
if name:
if frappe.local.request.method=="GET":
frappe.local.response.update({
"doclist": frappe.client.get(doctype,
name)})
if frappe.local.request.method=="POST":
frappe.local.response.update({
"doclist": frappe.client.insert(frappe.local.form_dict.doclist)})
frappe.db.commit()
if frappe.local.request.method=="PUT":
frappe.local.response.update({
"doclist":frappe.client.save(frappe.local.form_dict.doclist)})
frappe.db.commit()
if frappe.local.request.method=="DELETE":
frappe.client.delete(doctype, name)
frappe.local.response.message = "ok"
elif doctype:
if frappe.local.request.method=="GET":
frappe.local.response.update({
"data": frappe.call(frappe.widgets.reportview.execute,
doctype, **frappe.local.form_dict)})
else:
raise frappe.DoesNotExistError
else:
raise frappe.DoesNotExistError
except frappe.DoesNotExistError, e:
report_error(404)
except Exception, e:
report_error(500)
if frappe.local.request.method=="PUT":
frappe.local.response.update({
"doclist":frappe.client.save(frappe.local.form_dict.doclist)})
frappe.db.commit()
if frappe.local.request.method=="DELETE":
frappe.client.delete(doctype, name)
frappe.local.response.message = "ok"
elif doctype:
if frappe.local.request.method=="GET":
frappe.local.response.update({
"data": frappe.call(frappe.widgets.reportview.execute,
doctype, **frappe.local.form_dict)})
else:
raise frappe.DoesNotExistError
else:
raise frappe.DoesNotExistError
build_response()
return build_response("json")

+ 54
- 37
frappe/app.py Ver arquivo

@@ -25,65 +25,82 @@ local_manager = LocalManager([frappe.local])
_site = None
_sites_path = os.environ.get("SITES_PATH", ".")

def handle_session_stopped():
res = Response("""<html>
<body style="background-color: #EEE;">
<h3 style="width: 900px; background-color: #FFF; border: 2px solid #AAA; padding: 20px; font-family: Arial; margin: 20px auto">
Updating.
We will be back in a few moments...
</h3>
</body>
</html>""")
res.status_code = 503
res.content_type = 'text/html'
return res

@Request.application
def application(request):
frappe.local.request = request
response = None
try:
site = _site or get_site_name(request.host)
frappe.init(site=site, sites_path=_sites_path)
rollback = True
if not frappe.local.conf:
# site does not exist
raise NotFound
init_site(request)
make_form_dict(request)
frappe.local.http_request = frappe.auth.HTTPRequest()
frappe.local.form_dict = frappe._dict({ k:v[0] if isinstance(v, (list, tuple)) else v \
for k, v in (request.form or request.args).iteritems() })
frappe.local._response = Response()
frappe.http_request = frappe.auth.HTTPRequest()

if frappe.local.form_dict.cmd:
frappe.handler.handle()
response = frappe.handler.handle()
elif frappe.request.path.startswith("/api/"):
frappe.api.handle()
response = frappe.api.handle()
elif frappe.request.path.startswith('/backups'):
frappe.utils.response.download_backup(request.path)
response = frappe.utils.response.download_backup(request.path)
elif frappe.local.request.method in ('GET', 'HEAD'):
frappe.website.render.render(frappe.request.path[1:])
response = frappe.website.render.render(request.path)
else:
raise NotFound

except HTTPException, e:
return e
except frappe.AuthenticationError, e:
frappe._response.status_code=401
except frappe.SessionStopped, e:
frappe.local._response = handle_session_stopped()
response = frappe.utils.response.handle_session_stopped()
except (frappe.AuthenticationError,
frappe.PermissionError,
frappe.DoesNotExistError,
frappe.DuplicateEntryError,
frappe.OutgoingEmailError,
frappe.ValidationError), e:
response = frappe.utils.response.report_error(e.http_status_code)
if e.__class__ == frappe.AuthenticationError:
frappe.local.login_manager.clear_cookies()
else:
if frappe.local.request.method in ("POST", "PUT") and frappe.db:
frappe.db.commit()
rollback = False
finally:
_response = frappe.local._response
if frappe.local.request.method in ("POST", "PUT") and frappe.db and rollback:
frappe.db.rollback()
# set cookies
if response:
frappe.local.cookie_manager.flush_cookies(response=response)
frappe.destroy()
return response
def init_site(request):
site = _site or get_site_name(request.host)
frappe.init(site=site, sites_path=_sites_path)
if not frappe.local.conf:
# site does not exist
raise NotFound
def make_form_dict(request):
frappe.local.form_dict = frappe._dict({ k:v[0] if isinstance(v, (list, tuple)) else v \
for k, v in (request.form or request.args).iteritems() })
return _response

application = local_manager.make_middleware(application)

def serve(port=8000, profile=False, site=None, sites_path='.'):
global application, _site, _sites_path
_site = site
@@ -102,6 +119,6 @@ def serve(port=8000, profile=False, site=None, sites_path='.'):
application = StaticDataMiddleware(application, {
'/files': os.path.abspath(sites_path)
})
run_simple('0.0.0.0', int(port), application, use_reloader=True,
use_debugger=True, use_evalex=True)

+ 42
- 35
frappe/auth.py Ver arquivo

@@ -2,13 +2,15 @@
# MIT License. See license.txt

from __future__ import unicode_literals
import datetime

import frappe
import frappe.database
import frappe.utils
import frappe.utils.user
from frappe import conf
from frappe.sessions import Session
from frappe.modules.patch_handler import check_session_stopped

class HTTPRequest:
def __init__(self):
@@ -33,11 +35,12 @@ class HTTPRequest:

# login
frappe.local.login_manager = LoginManager()
# write out latest cookies
frappe.local.cookie_manager.init_cookies()

# check status
if frappe.db.get_global("__session_status")=='stop':
frappe.msgprint(frappe.db.get_global("__session_status_message"))
raise frappe.SessionStopped('Session Stopped')
check_session_stopped()

# load user
self.setup_user()
@@ -106,20 +109,23 @@ class LoginManager:
self.set_user_info()
def set_user_info(self):
# set sid again
frappe.local.cookie_manager.init_cookies()
info = frappe.db.get_value("User", self.user,
["user_type", "first_name", "last_name", "user_image"], as_dict=1)
if info.user_type=="Website User":
frappe.local._response.set_cookie("system_user", "no")
frappe.local.cookie_manager.set_cookie("system_user", "no")
frappe.local.response["message"] = "No App"
else:
frappe.local._response.set_cookie("system_user", "yes")
frappe.local.cookie_manager.set_cookie("system_user", "yes")
frappe.local.response['message'] = 'Logged In'

full_name = " ".join(filter(None, [info.first_name, info.last_name]))
frappe.response["full_name"] = full_name
frappe._response.set_cookie("full_name", full_name)
frappe._response.set_cookie("user_id", self.user)
frappe._response.set_cookie("user_image", info.user_image or "")
frappe.local.cookie_manager.set_cookie("full_name", full_name)
frappe.local.cookie_manager.set_cookie("user_id", self.user)
frappe.local.cookie_manager.set_cookie("user_image", info.user_image or "")
def make_session(self, resume=False):
# start session
@@ -161,7 +167,7 @@ class LoginManager:
def run_trigger(self, event='on_login'):
for method in frappe.get_hooks().get(event, []):
frappe.get_attr(method)(self)
frappe.call(frappe.get_attr(method), login_manager=self)
def validate_ip_address(self):
"""check if IP Address is valid"""
@@ -212,44 +218,45 @@ class LoginManager:
clear_sessions(user)

if user == frappe.session.user:
frappe.session.sid = ""
frappe.local._response.delete_cookie("full_name")
frappe.local._response.delete_cookie("user_id")
frappe.local._response.delete_cookie("sid")
frappe.local._response.set_cookie("full_name", "")
frappe.local._response.set_cookie("user_id", "")
frappe.local._response.set_cookie("sid", "")
self.clear_cookies()
def clear_cookies(self):
frappe.session.sid = ""
frappe.local.cookie_manager.delete_cookie(["full_name", "user_id", "sid", "user_image", "system_user"])

class CookieManager:
def __init__(self):
pass
self.cookies = {}
self.to_delete = []
def set_cookies(self):
def init_cookies(self):
if not frappe.local.session.get('sid'): return
import datetime

# sid expires in 3 days
expires = datetime.datetime.now() + datetime.timedelta(days=3)
if frappe.session.sid:
frappe.local._response.set_cookie("sid", frappe.session.sid, expires = expires)
self.cookies["sid"] = {"value": frappe.session.sid, "expires": expires}
if frappe.session.session_country:
frappe.local._response.set_cookie('country', frappe.session.get("session_country"))
self.cookies["country"] = {"value": frappe.session.get("session_country")}
def set_cookie(self, key, value, expires=None):
self.cookies[key] = {"value": value, "expires": expires}
def delete_cookie(self, to_delete):
if not isinstance(to_delete, (list, tuple)):
to_delete = [to_delete]
def set_remember_me(self):
from frappe.utils import cint
self.to_delete.extend(to_delete)
if not cint(frappe.form_dict.get('remember_me')): return
def flush_cookies(self, response):
for key, opts in self.cookies.items():
response.set_cookie(key, opts.get("value"), expires=opts.get("expires"))
# expires yesterday!
expires = datetime.datetime.now() + datetime.timedelta(days=-1)
for key in set(self.to_delete):
response.set_cookie(key, "", expires=expires)
remember_days = frappe.db.get_value('Control Panel', None,
'remember_for_days') or 7
import datetime
expires = datetime.datetime.now() + \
datetime.timedelta(days=remember_days)

frappe.local._response.set_cookie["remember_me"] = 1


def _update_password(user, password):
frappe.db.sql("""insert into __Auth (user, `password`)
values (%s, password(%s))


+ 7
- 1
frappe/core/doctype/doctype/doctype.py Ver arquivo

@@ -129,10 +129,16 @@ class DocType:
self.doc.doctype, self.doc.name), scrub(self.doc.name) + '.py')

if not os.path.exists(pypath):
# get app publisher for copyright
app = frappe.local.module_app[frappe.scrub(self.doc.module)]
if not app:
frappe.throw("App not found!")
app_publisher = frappe.get_hooks(hook="app_publisher", app_name=app)[0]
with open(pypath, 'w') as pyfile:
with open(os.path.join(get_module_path("core"), "doctype", "doctype",
"doctype_template.py"), 'r') as srcfile:
pyfile.write(srcfile.read())
pyfile.write(srcfile.read().format(app_publisher=app_publisher))
def make_amendable(self):
"""


+ 2
- 2
frappe/core/doctype/doctype/doctype_template.py Ver arquivo

@@ -1,5 +1,5 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# GNU General Public License. See license.txt
# Copyright (c) 2013, {app_publisher}
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe


+ 35
- 0
frappe/exceptions.py Ver arquivo

@@ -0,0 +1,35 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals

# BEWARE don't put anything in this file except exceptions

class ValidationError(Exception):
http_status_code = 417

class AuthenticationError(Exception):
http_status_code = 401

class PermissionError(Exception):
http_status_code = 403

class DoesNotExistError(ValidationError):
http_status_code = 404

class DuplicateEntryError(Exception):
http_status_code = 409
class OutgoingEmailError(Exception):
http_status_code = 501
class SessionStopped(Exception):
http_status_code = 503
class DataError(Exception): pass
class UnknownDomainError(Exception): pass
class MappingMismatchError(ValidationError): pass
class InvalidStatusError(ValidationError): pass
class MandatoryError(ValidationError): pass
class InvalidSignatureError(ValidationError): pass
class RateLimitExceededError(ValidationError): pass

+ 3
- 28
frappe/handler.py Ver arquivo

@@ -8,7 +8,7 @@ import frappe.utils
import frappe.sessions
import frappe.utils.file_manager
import frappe.widgets.form.run_method
from frappe.utils.response import build_response, report_error
from frappe.utils.response import build_response

@frappe.whitelist(allow_guest=True)
def startup():
@@ -64,33 +64,9 @@ def handle():
cmd = frappe.local.form_dict.cmd
if cmd!='login':
status_codes = {
frappe.PermissionError: 403,
frappe.AuthenticationError: 401,
frappe.DoesNotExistError: 404,
frappe.DuplicateEntryError: 409,
frappe.SessionStopped: 503,
frappe.OutgoingEmailError: 501
}
try:
execute_cmd(cmd)
except Exception, e:
report_error(status_codes.get(e.__class__, 500))
else:
if frappe.local.request.method in ("POST", "PUT") and frappe.db:
frappe.db.commit()
else:
# commit for login
if frappe.local.request.method in ("POST", "PUT") and frappe.db:
frappe.db.commit()
execute_cmd(cmd)
build_response()

if frappe.db:
frappe.db.close()
if frappe._memc:
frappe._memc.disconnect_all()
return build_response("json")

def execute_cmd(cmd):
"""execute a request as python module"""
@@ -102,7 +78,6 @@ def execute_cmd(cmd):
raise frappe.PermissionError('Not Allowed, %s' % str(method))
else:
if not method in frappe.whitelisted:
frappe._response.status_code = 403
frappe.msgprint('Not Allowed, %s' % str(method))
raise frappe.PermissionError('Not Allowed, %s' % str(method))


+ 1
- 1
frappe/hooks.txt Ver arquivo

@@ -1,6 +1,6 @@
app_name = frappe
app_title = Frappe Framework
app_publisher = Web Notes Technologies
app_publisher = Web Notes Technologies Pvt. Ltd. and Contributors
app_description = Full Stack Web Application Framwork in Python
app_icon = assets/frappe/images/frappe.svg
app_version = 4.0.0-wip


+ 5
- 0
frappe/modules/patch_handler.py Ver arquivo

@@ -114,6 +114,11 @@ def block_user(block):
frappe.db.set_global('__session_status', block and 'stop' or None)
frappe.db.set_global('__session_status_message', block and msg or None)
frappe.db.commit()
def check_session_stopped():
if frappe.db.get_global("__session_status")=='stop':
frappe.msgprint(frappe.db.get_global("__session_status_message"))
raise frappe.SessionStopped('Session Stopped')

def setup():
frappe.db.sql("""CREATE TABLE IF NOT EXISTS `__PatchLog` (


BIN
frappe/public/images/ui/field.jpg Ver arquivo

Antes Depois
Largura: 1600  |  Altura: 1066  |  Tamanho: 198 KiB

BIN
frappe/public/images/ui/random-polygons.jpg Ver arquivo

Antes Depois
Largura: 1920  |  Altura: 1600  |  Tamanho: 258 KiB

BIN
frappe/public/images/ui/wallpaper.jpg Ver arquivo

Antes Depois
Largura: 1920  |  Altura: 1200  |  Tamanho: 664 KiB

+ 3
- 3
frappe/public/js/frappe/misc/user.js Ver arquivo

@@ -30,10 +30,10 @@ frappe.avatar = function(user, large, title) {
});
}

frappe.ui.set_user_background = function(src) {
if(!src) src = "assets/frappe/images/ui/random-polygons.jpg";
frappe.ui.set_user_background = function(src, size) {
if(!src) src = "assets/frappe/images/ui/wallpaper.jpg";
frappe.dom.set_style(repl('#page-desktop { \
background: url("%(src)s") center center fixed; \
background: url("%(src)s") center center; \
}', {src:src}))
}



+ 1
- 4
frappe/sessions.py Ver arquivo

@@ -59,7 +59,7 @@ def clear_sessions(user=None, keep_current=False):
user = frappe.session.user
for sid in frappe.db.sql("""select sid from tabSessions where user=%s""", (user,)):
if keep_current and frappe.session.sid==sid[0]:
pass
continue
else:
frappe.cache().delete_value("session:" + sid[0])
frappe.db.sql("""delete from tabSessions where sid=%s""", (sid[0],))
@@ -104,9 +104,6 @@ class Session:
# set local session
frappe.local.session = self.data

# write out latest cookies
frappe.local.cookie_manager.set_cookies()

def start(self):
"""start a new session"""
# generate sid


+ 5
- 1
frappe/templates/includes/login.js Ver arquivo

@@ -102,7 +102,11 @@ login.login_handlers = {
}
},
401: function(xhr, data) {
frappe.msgprint("Invalid Login");
if(xhr.responseJSON) {
data = xhr.responseJSON;
}
var message = data._server_messages ? JSON.parse(data._server_messages).join("\n") : "Invalid Login";
frappe.msgprint(message);
}
}



+ 1
- 1
frappe/templates/pages/login.py Ver arquivo

@@ -33,7 +33,7 @@ oauth2_providers = {
"redirect_uri": "/api/method/frappe.templates.pages.login.login_via_google",
"auth_url_data": {
"scope": "https://www.googleapis.com/auth/userinfo.user https://www.googleapis.com/auth/userinfo.email",
"scope": "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
"response_type": "code"
},


+ 88
- 68
frappe/utils/response.py Ver arquivo

@@ -12,6 +12,7 @@ from frappe import _
import frappe.utils
import frappe.sessions
import frappe.model.utils
import werkzeug.utils
from werkzeug.local import LocalProxy
from werkzeug.wsgi import wrap_file
from werkzeug.wrappers import Response
@@ -20,61 +21,49 @@ from werkzeug.exceptions import NotFound, Forbidden
def report_error(status_code):
if status_code!=404 or frappe.conf.logging:
frappe.errprint(frappe.utils.get_traceback())
frappe._response.status_code = status_code
if frappe.request_method == "POST":
frappe.db.rollback()
response = build_response("json")
response.status_code = status_code
return response

def build_response():
print_map = {
'csv': print_csv,
'download': print_raw,
'json': print_json,
'page': print_page,
def build_response(response_type=None):
response_type_map = {
'csv': as_csv,
'download': as_raw,
'json': as_json,
'page': as_page,
'redirect': redirect
}
print_map.get(frappe.response.get('type'), print_json)()

def print_page():
"""print web page"""
from frappe.website.render import render
render(frappe.response['page_name'])

def print_json():
make_logs()
cleanup_docs()
frappe._response.headers["Content-Type"] = "text/json; charset: utf-8"
print_zip(json.dumps(frappe.local.response, default=json_handler, separators=(',',':')))
def redirect():
frappe._response.data = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="{location}">/</a>.
If not click the link.'""".format(location=frappe.response.location)
frappe._response.headers["Content-Type"] = "text/html; charset: utf-8"
frappe._response.status_code = frappe.response.status_code or 302
frappe._response.location = frappe.response.location
return response_type_map[frappe.response.get('type') or response_type]()
def cleanup_docs():
if frappe.response.get('docs') and type(frappe.response['docs'])!=dict:
frappe.response['docs'] = frappe.model.utils.compress(frappe.response['docs'])
def print_csv():
frappe._response.headers["Content-Type"] = \
def as_csv():
response = Response()
response.headers["Content-Type"] = \
"text/csv; charset: utf-8"
frappe._response.headers["Content-Disposition"] = \
response.headers["Content-Disposition"] = \
"attachment; filename=%s.csv" % frappe.response['doctype'].replace(' ', '_')
frappe._response.data = frappe.response['result']
response.data = frappe.response['result']
return response

def print_raw():
frappe._response.headers["Content-Type"] = \
def as_raw():
response = Response()
response.headers["Content-Type"] = \
mimetypes.guess_type(frappe.response['filename'])[0] or "application/unknown"
frappe._response.headers["Content-Disposition"] = \
response.headers["Content-Disposition"] = \
"filename=%s" % frappe.response['filename'].replace(' ', '_')
frappe._response.data = frappe.response['filecontent']
response.data = frappe.response['filecontent']
return response

def as_json():
make_logs()
cleanup_docs()
response = Response()
response.headers["Content-Type"] = "text/json; charset: utf-8"
response = gzip(json.dumps(frappe.local.response, default=json_handler, separators=(',',':')),
response=response)
return response
def make_logs():
"""make strings for msgprint and errprint"""
if frappe.error_log:
@@ -87,15 +76,31 @@ def make_logs():
if frappe.debug_log and frappe.conf.get("logging") or False:
frappe.response['_debug_messages'] = json.dumps(frappe.local.debug_log)

def print_zip(response):
response = response.encode('utf-8')
orig_len = len(response)
def cleanup_docs():
if frappe.response.get('docs') and type(frappe.response['docs'])!=dict:
frappe.response['docs'] = frappe.model.utils.compress(frappe.response['docs'])
def gzip(data, response):
data = data.encode('utf-8')
orig_len = len(data)
if accept_gzip() and orig_len>512:
response = compressBuf(response)
frappe._response.headers["Content-Encoding"] = "gzip"
data = compressBuf(data)
response.headers["Content-Encoding"] = "gzip"
frappe._response.headers["Content-Length"] = str(len(response))
frappe._response.data = response
response.headers["Content-Length"] = str(len(data))
response.data = data
return response
def accept_gzip():
if "gzip" in frappe.get_request_header("HTTP_ACCEPT_ENCODING", ""):
return True

def compressBuf(buf):
zbuf = cStringIO.StringIO()
zfile = gzip.GzipFile(mode = 'wb', fileobj = zbuf, compresslevel = 5)
zfile.write(buf)
zfile.close()
return zbuf.getvalue()
def json_handler(obj):
"""serialize non-serializable data for json"""
@@ -108,31 +113,30 @@ def json_handler(obj):
else:
raise TypeError, """Object of type %s with value of %s is not JSON serializable""" % \
(type(obj), repr(obj))

def accept_gzip():
if "gzip" in frappe.get_request_header("HTTP_ACCEPT_ENCODING", ""):
return True

def compressBuf(buf):
zbuf = cStringIO.StringIO()
zfile = gzip.GzipFile(mode = 'wb', fileobj = zbuf, compresslevel = 5)
zfile.write(buf)
zfile.close()
return zbuf.getvalue()

def as_page():
"""print web page"""
from frappe.website.render import render
return render(frappe.response['page_name'])
def redirect():
return werkzeug.utils.redirect(frappe.response.location)
def download_backup(path):
try:
frappe.only_for(("System Manager", "Administrator"))
except frappe.PermissionError:
raise Forbidden(_("You need to be logged in and have System Manager Role to be able to access backups."))
send_private_file(path)

return send_private_file(path)

def send_private_file(path):
path = os.path.join(frappe.local.conf.get('private_path', 'private'), path.strip("/"))

if frappe.local.request.headers.get('X-Use-X-Accel-Redirect'):
path = '/' + path
frappe.local._response.headers['X-Accel-Redirect'] = path
response = Response()
response.headers['X-Accel-Redirect'] = path
else:
filename = os.path.basename(path)
filepath = frappe.utils.get_site_path(path)
@@ -140,6 +144,22 @@ def send_private_file(path):
f = open(filepath, 'rb')
except IOError:
raise NotFound
frappe.local._response = Response(wrap_file(frappe.local.request.environ, f))
frappe.local._response.headers.add('Content-Disposition', 'attachment', filename=filename)
frappe.local._response.headers['Content-Type'] = mimetypes.guess_type(filename)[0] or 'application/octet-stream'

response = Response(wrap_file(frappe.local.request.environ, f))
response.headers.add('Content-Disposition', 'attachment', filename=filename)
response.headers['Content-Type'] = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
return response

def handle_session_stopped():
response = Response("""<html>
<body style="background-color: #EEE;">
<h3 style="width: 900px; background-color: #FFF; border: 2px solid #AAA; padding: 20px; font-family: Arial; margin: 20px auto">
Updating.
We will be back in a few moments...
</h3>
</body>
</html>""")
response.status_code = 503
response.content_type = 'text/html'
return res

+ 15
- 14
frappe/website/render.py Ver arquivo

@@ -4,17 +4,18 @@
from __future__ import unicode_literals
import frappe
import mimetypes, json
from werkzeug.wrappers import Response

from frappe.website.context import get_context
from frappe.website.utils import scrub_relative_urls, get_home_page, can_cache

from frappe.website.permissions import get_access, clear_permissions

class PageNotFoundError(Exception): pass

def render(path):
"""render html page"""
path = resolve_path(path)
frappe.local.is_ajax = frappe.get_request_header("X-Requested-With")=="XMLHttpRequest"
path = resolve_path(path.lstrip("/"))
try:
data = render_page(path)
@@ -22,9 +23,12 @@ def render(path):
path = "error"
data = render_page(path)
data = set_content_type(data, path)
frappe._response.data = data
frappe._response.headers[b"X-Page-Name"] = path.encode("utf-8")
# build response
response = Response()
response.data = set_content_type(response, data, path)
response.headers[b"X-Page-Name"] = path.encode("utf-8")
response.headers[b"X-From-Cache"] = frappe.local.response.from_cache or False
return response
def render_page(path):
"""get page html"""
@@ -39,9 +43,7 @@ def render_page(path):
out = out.get("data")
if out:
if hasattr(frappe, "_response"):
frappe._response.headers[b"X-From-Cache"] = True
frappe.local.response.from_cache = True
return out
return build(path)
@@ -75,8 +77,7 @@ def build_page(path):
return html
def is_ajax():
return (frappe.get_request_header("X-Requested-With")=="XMLHttpRequest"
if hasattr(frappe.local, "_response") else False)
return getattr(frappe.local, "is_ajax")
def resolve_path(path):
if not path:
@@ -90,17 +91,17 @@ def resolve_path(path):
return path

def set_content_type(data, path):
def set_content_type(response, data, path):
if isinstance(data, dict):
frappe._response.headers[b"Content-Type"] = b"application/json; charset: utf-8"
response.headers[b"Content-Type"] = b"application/json; charset: utf-8"
data = json.dumps(data)
return data
frappe._response.headers[b"Content-Type"] = b"text/html; charset: utf-8"
response.headers[b"Content-Type"] = b"text/html; charset: utf-8"
if "." in path and not path.endswith(".html"):
content_type, encoding = mimetypes.guess_type(path)
frappe._response.headers[b"Content-Type"] = content_type.encode("utf-8")
response.headers[b"Content-Type"] = content_type.encode("utf-8")
return data



Carregando…
Cancelar
Salvar