clamp the subject line of error emails to be no more than 115 chars
[sgn.git] / lib / SGN / Exception.pm
blob2d7b465cb388e5b9a50ab9a626381cd02f5bc913
1 =head1 NAME
3 SGN::Exception - expressive exception object for web applications
5 =head1 SYNOPSIS
7 die SGN::Exception->new(
9 title => 'Froozle Error',
10 public_message => "Cannot process the froozle.",
11 developer_message => "Froozle was '$froozle', path was '$fogbat_path'.",
13 http_status => 406,
14 is_server_error => 1,
15 is_client_error => 0,
17 # developers need to be notified that this happened
18 notify => 1,
22 =head1 DESCRIPTION
24 The SGN::Exception object is meant to hold a wide variety of
25 information about the nature of an exception or error condition.
26 Nearly all the attributes of the exception object are optional.
28 =cut
30 package SGN::Exception;
31 use Moose;
32 use Scalar::Util ();
34 # make catalyst use this exception class
35 { no warnings 'once';
36 $Catalyst::Exception::CATALYST_EXCEPTION_CLASS = __PACKAGE__;
39 with 'Catalyst::Exception::Basic';
41 use overload
43 q[""] => 'stringify',
44 fallback => 1,
47 =head1 ATTRIBUTES
49 All attributes are read-only. None are required.
51 =head2 public_message
53 String, publicly-visible message for this error. Should not reveal
54 details that could have security implications.
56 =cut
58 has 'public_message' => (
59 is => 'ro',
60 isa => 'Maybe[Str]',
63 =head2 developer_message
65 String, private message for developers. Should be included in error
66 notifications sent to developers, debug backtraces, etc.
68 =cut
70 has 'developer_message' => (
71 is => 'ro',
72 isa => 'Maybe[Str]',
75 #TODO: redundant, deleteme
76 has 'explanation' => (
77 is => 'ro',
78 isa => 'Maybe[Str]',
81 =head2 title
83 Optional string, user-visible title for the exception as presented to the user.
85 =cut
87 has 'title' => (
88 is => 'ro',
89 isa => 'Maybe[Str]',
92 =head2 is_server_error
94 Boolean, true if this error indicates a problem on the server side.
96 Defaults to true most of the time, but defaults to false if
97 is_client_error is explicitly set to true.
99 =cut
101 has 'is_server_error' => (
102 is => 'ro',
103 isa => 'Bool',
104 default => 1,
107 =head2 is_client_error
109 Boolean, true if this error indicates a problem on the client side.
111 Defaults to false most of the time, but default to true if
112 is_server_error is set and false.
114 =cut
116 has 'is_client_error' => (
117 is => 'ro',
118 isa => 'Bool',
119 default => 0,
122 =head2 http_status
124 Explicitly set the status code of the HTTP response for this error
125 condition.
127 Defaults to 500 (Internal Server Error) if is_server_error is set,
128 else 400 (Bad Request) if is_client_error is set, or 200 (OK) if
129 is_client_error and is_server_error are both false.
131 =cut
133 has 'http_status' => (
134 is => 'ro',
135 isa => 'Int',
136 default => sub {
137 my $self = shift;
138 $self->is_server_error ? 500 :
139 $self->is_client_error ? 400 :
144 =head2 notify
146 Flag indicating whether developers should be actively notified that
147 this exception occurred.
149 Boolean, defaults to true if is_server_error is set, false otherwise.
151 =cut
153 has 'notify' => (
154 is => 'ro',
155 isa => 'Bool',
156 lazy_build => 1,
157 ); sub _build_notify {
158 shift->is_server_error
161 around 'BUILDARGS' => sub {
162 my $orig = shift;
163 my $class = shift;
164 my %args = @_ > 1 ? @_ : ( message => @_ );
166 $args{developer_message} ||= $args{message};
167 $args{message} ||= $args{developer_message} || $args{public_message} || '(no message)';
169 if( defined $args{is_client_error} && !$args{is_client_error} ) {
170 $args{is_server_error} = 1 unless defined $args{is_server_error};
172 if( defined $args{is_server_error} && !$args{is_server_error} ) {
173 $args{is_client_error} = 1 unless defined $args{is_client_error};
175 if( $args{is_client_error} && ! defined $args{is_server_error} ) {
176 $args{is_server_error} = 0;
179 return $class->$orig( %args );
182 =head1 METHODS
184 =head2 stringify
186 Return a plaintext string representation of this exception, suitable
187 for display in consoles and so forth.
189 =cut
191 sub stringify {
192 my $self = shift;
193 return
194 ($self->public_message || '') . "\n"
195 .'Developer message: '
196 .($self->developer_message || 'none');
199 __PACKAGE__->meta->make_immutable;