การเพิ่มข้อยกเว้นใหม่เป็นข้อผิดพลาด HTTP ในพีระมิด

ฉันมีเว็บแอปใน python Pyramid ซึ่งเรียกโค้ดอื่นๆ มากมายใน python ซึ่งอาจทำให้เกิดข้อยกเว้น แทนที่จะให้ผู้ใช้ได้รับ "ข้อผิดพลาดภายใน 500" ฉันต้องการให้พวกเขาได้รับข้อผิดพลาดที่เจาะจงมากขึ้น เช่น หาก MyException ถูกโยนทิ้ง ให้แสดงข้อผิดพลาด 503 ฉันพยายามทำสิ่งนี้:

@view_config(context=MyException, permission='view')
def custom_exc(exc, request):
   raise HTTPServiceUnavailable(exc.message)

อย่างไรก็ตาม การดำเนินการดังกล่าวล้มเหลวเนื่องจากไม่ได้รับอนุญาตด้วยเหตุผลบางประการ:

HTTPForbidden: Unauthorized: custom_exc failed permission check

ACL ของฉันเป็นดังนี้:

class RootFactory(object):
    __acl__ = [
        (Allow, 'admin', ('view',))
        ]

ฉันเชื่อมต่อกับผู้ใช้ ผู้ดูแลระบบ และทำงานได้อย่างสมบูรณ์แบบสำหรับมุมมองอื่น

ไม่มีใครรู้วิธีการแก้ปัญหานี้หรือวิธี "เชื่อมโยง" ข้อยกเว้นในพีระมิดด้วยวิธีอื่นหรือไม่


person KimiNewt    schedule 26.01.2015    source แหล่งที่มา
comment
คุณได้ดูมุมมองข้อยกเว้น? ฉันเคยใช้สิ่งเหล่านั้นเพื่อบันทึกและส่งคืนข้อผิดพลาดเฉพาะ แม้ว่าฉันจะไม่พบข้อผิดพลาดในการอนุญาตก็ตาม   -  person Peter Tirrell    schedule 29.01.2015


คำตอบ (1)


เรียนรู้จาก เวอร์ชันที่กำหนดเองของแอปพลิเคชันตัวอย่าง ToDoPyramid ที่มีชื่อเสียง ด้วยวิธีนี้ ฉันจะแปลเหตุการณ์ทางเทคนิคภายใน ซึ่งเป็นข้อยกเว้นของฐานข้อมูล ให้เป็นข้อความเฉพาะแอปพลิเคชันที่มีความหมายภายในโค้ดมุมมองข้อยกเว้นแบบกำหนดเอง ผู้ชายบางคนเรียกสิ่งนี้ว่าชั้นของนามธรรมหรือการซ่อนข้อมูล

อย่าปกป้องมุมมองข้อยกเว้นเหล่านี้ด้วยการอนุญาต เนื่องจากคุณควรปกป้องโค้ดที่ทำสิ่งต่าง ๆ และสามารถเพิ่มข้อยกเว้นได้

from sqlalchemy.exc import OperationalError as SqlAlchemyOperationalError

@view_config(context=SqlAlchemyOperationalError)
def failed_sqlalchemy(exception, request):
    """catch missing database, logout and redirect to homepage, add flash message with error
    implementation inspired by pylons group message
    https://groups.google.com/d/msg/pylons-discuss/BUtbPrXizP4/0JhqB2MuoL4J
    """

    msg = 'There was an error connecting to database'
    request.session.flash(msg, queue='error')
    headers = forget(request)
    # Send the user back home, everything else is protected
    return HTTPFound(request.route_url('home'), headers=headers)
person Sascha Gottfried    schedule 29.01.2015