Mercurial > pub > Impl
annotate Lib/IMPL/Web/Application/Response.pm @ 65:2840c4c85db8
Application configuration improvements
Documentation
author | wizard |
---|---|
date | Tue, 16 Mar 2010 17:36:13 +0300 |
parents | 76b878ad6596 |
children | 9f5795a10939 |
rev | line source |
---|---|
59
0f3e369553bd
Rewritten property implementation (probably become slower but more flexible)
wizard
parents:
58
diff
changeset
|
1 package IMPL::Web::Application::Response; |
57 | 2 use strict; |
3 | |
4 use base qw(IMPL::Object IMPL::Object::Autofill); | |
5 | |
6 require IMPL::Exception; | |
7 require CGI; | |
8 require CGI::Cookie; | |
9 | |
58 | 10 use Carp; |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
11 use Encode; |
57 | 12 use IMPL::Class::Property; |
13 | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
14 #todo: add binary method to set a binary encoding, set it automatic when type isn't a text |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
15 |
57 | 16 BEGIN { |
17 public property query => prop_get | owner_set; # cgi query | |
18 public property status => prop_all, { validator => \&_checkHeaderPrinted }; | |
19 public property contentType => prop_all, { validator => \&_checkHeaderPrinted }; # String | |
58 | 20 public property charset => { get => \&_charset, set => \&_charset }, { validator => \&_checkHeaderPrinted }; |
57 | 21 public property expires => prop_all, { validator => \&_checkHeaderPrinted }; |
22 public property cookies => prop_all, { validator => \&_checkHeaderPrinted }; # Hash | |
23 | |
58 | 24 public property buffered => prop_all, { validator => \&_canChangeBuffer }; # Boolean |
57 | 25 public property streamOut => prop_get | owner_set; # stream |
26 public property streamBody => {get => \&getStreamBody }; # stream | |
58 | 27 public property isHeaderPrinted => prop_get | owner_set; # Boolean |
57 | 28 |
29 private property _bufferBody => prop_all; | |
30 private property _streamBody => prop_all; | |
31 } | |
32 | |
33 __PACKAGE__->PassThroughArgs; | |
34 | |
35 sub CTOR { | |
36 my ($this,%args) = @_; | |
37 | |
58 | 38 $this->query(CGI->new($this->query() | {})) unless $this->query; |
57 | 39 |
65 | 40 if (lc $this->streamOut eq 'memory') { |
41 my $dummy = ''; | |
42 open my $hout, '>:encoding(utf8)', \$dummy or die new IMPL::Exception("Failed to create memory stream",$!); | |
43 $this->streamOut($hout); | |
44 } elsif (not $this->streamOut) { | |
45 $this->streamOut(*STDOUT); | |
46 } else { | |
47 die new IMPL::InvalidArgumentException("Invalid parameter value",$this->streamOut); | |
48 } | |
49 | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
50 $this->buffered(1) unless defined $this->buffered; |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
51 binmode $this->streamOut, ":encoding(".$this->charset.")"; |
57 | 52 } |
53 | |
54 sub _checkHeaderPrinted { | |
55 my ($this,$value) = @_; | |
56 | |
57 die new IMPL::InvalidOperationException() if $this->isHeaderPrinted; | |
58 } | |
59 | |
58 | 60 sub _canChangeBuffer { |
61 my ($this,$value) = @_; | |
62 | |
63 die new IMPL::InvalidOperationException() if $this->isHeaderPrinted or $this->_streamBody; | |
64 } | |
65 | |
66 sub _charset { | |
67 my $this = shift; | |
68 | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
69 if (@_) { |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
70 my $charset = $this->query->charset(@_); |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
71 |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
72 my $hout = $this->streamOut; |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
73 |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
74 binmode $hout; |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
75 binmode $hout, ":encoding($charset)"; |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
76 |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
77 return $charset; |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
78 } else { |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
79 return $this->query->charset; |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
80 } |
58 | 81 } |
82 | |
57 | 83 sub _PrintHeader { |
84 my ($this) = @_; | |
85 | |
86 unless ($this->isHeaderPrinted) { | |
87 $this->isHeaderPrinted(1); | |
88 | |
89 my %opt; | |
90 | |
91 $opt{-type} = $this->contentType if $this->contentType; | |
92 $opt{-status} = $this->status if $this->status; | |
93 $opt{-expires} = $this->expires if $this->expires; | |
94 | |
95 my $refCookies = $this->cookies; | |
96 $opt{-cookie} = [map CGI::Cookie->new(-name => $_, $refCookies->{$_} ), keys %$refCookies] if $refCookies; | |
97 | |
98 my $hOut = $this->streamOut; | |
99 | |
100 print $hOut $this->query->header( | |
101 %opt | |
102 ); | |
103 } | |
104 } | |
105 | |
106 sub getStreamBody { | |
107 my ($this) = @_; | |
108 | |
58 | 109 return undef unless $this->streamOut; |
57 | 110 |
58 | 111 unless ($this->_streamBody) { |
112 if ($this->buffered) { | |
113 my $buffer = ""; | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
114 |
58 | 115 $this->_bufferBody(\$buffer); |
116 | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
117 open my $hBody, ">:encoding(utf-8)", \$buffer or die new IMPL::Exception("Failed to create buffer",$!); |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
118 |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
119 Encode::_utf8_on($buffer); |
58 | 120 |
121 $this->_streamBody($hBody); | |
122 } else { | |
123 $this->_PrintHeader(); | |
124 $this->_streamBody($this->streamOut); | |
125 } | |
57 | 126 } |
58 | 127 |
128 return $this->_streamBody; | |
57 | 129 } |
130 | |
131 sub Complete { | |
132 my ($this) = @_; | |
133 | |
134 return 0 unless $this->streamOut; | |
135 | |
136 my $hOut = $this->streamOut; | |
137 | |
138 $this->_PrintHeader(); | |
139 | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
140 $this->_streamBody(undef); |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
141 |
57 | 142 if ($this->buffered) { |
143 print $hOut ${$this->_bufferBody}; | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
59
diff
changeset
|
144 } |
57 | 145 |
146 $this->_bufferBody(undef); | |
147 $this->streamOut(undef); | |
148 | |
149 return 1; | |
150 } | |
151 | |
152 sub Discard { | |
153 my ($this) = @_; | |
154 | |
58 | 155 carp "Discarding sent response" if $this->isHeaderPrinted; |
156 | |
57 | 157 $this->_streamBody(undef); |
158 $this->_bufferBody(undef); | |
159 $this->streamOut(undef); | |
160 } | |
161 | |
162 1; | |
163 | |
164 __END__ | |
165 | |
166 =pod | |
167 | |
58 | 168 =head1 DESCRIPTION |
57 | 169 |
58 | 170 Ответ сервера на CGI запрос, позволяет сформировать основные свойства заголовка и тело запроса. |
171 | |
172 Объект позволяет буфферизировать вывод в тело ответа, что позволяет отменить или изменить | |
173 ответ в последний момент. | |
174 | |
175 Свойство C< isHeaderPrinted > можно использовать для определения были ли отправлены какие-нибудь | |
176 данные клиенту. | |
177 | |
178 =head1 PROPERTIES | |
179 | |
180 =head2 HTTP Header | |
181 | |
182 Свойства отвечающие за заголовок HTTP ответа. Эти своства могут быть изменены до тех пор пока | |
183 не будет отправлен заголовок. В противном случае выдается исключение C< IMPL::InvalidOperationException >. | |
184 | |
185 =over | |
186 | |
187 =item C< query > | |
188 | |
189 CGI запрос, который используется для вывода данных, заголовка и пр. Существует всегда. | |
190 | |
191 =item C< status > | |
192 | |
193 Код ошибки HTTP. Например, '200 OK'. По умолчанию не установлен, при отправке клиенту бедт отправлен '200 ОК'. | |
194 | |
195 =item C< contentType > | |
196 | |
197 Тип MIME. По умолчанию не установлен, подразумивается 'text/html'. | |
198 | |
199 =item C< charset > | |
200 | |
201 Кодировка, синоним свойства query->charset. | |
202 | |
203 =item C< expires > | |
204 | |
205 Определяет время жизни контента, например '+10m'. По умолчанию не задано и не передается. | |
206 | |
207 =item C< cookies > | |
208 | |
209 Хеш массив с cookies, например C< { cart => ['foo','bar'], display => 'list' } >. | |
210 | |
211 =back | |
212 | |
213 =head2 Response behaviour | |
214 | |
215 Свойства отвечающие за поведение ответа. | |
216 | |
217 =over | |
218 | |
219 =item C< buffered > | |
220 | |
221 C< True > - то тело ответа пишется в буффер и будет отправлено при вызове метода C< Complete >, | |
222 заголовок также будет отправлен после вызова метода C< Complete >. | |
223 | |
224 C< False > - тело ответа пишется непосредственно в поток к клиенту, при этом заголовок | |
225 будет отправлен при первом обращении к свойству C< streamBody > | |
226 | |
227 Это свойство можно менять до первого обращения к потоку для записи в тело ответа. | |
228 | |
229 =item C< streamOut > | |
230 | |
231 Стандартный вывод CGI приложения. | |
232 | |
233 =item C< streamBody > | |
234 | |
235 Поток для записи в тело ответа. | |
236 | |
237 =item C< isHeadPrinted > | |
238 | |
239 Признак того, что заголовок уже был отправлен клиенту. | |
240 | |
241 =back | |
242 | |
243 =head1 METHODS | |
244 | |
245 =over | |
246 | |
247 =item C< Complete > | |
248 | |
249 Завершает отправку ответа. | |
250 | |
251 =item C< Discard > | |
252 | |
253 Отменяет отправку ответа, при этом если часть данных (например, заголовок) | |
254 уже была отправлена, выдает предупреждение в STDERR. | |
255 | |
256 =back | |
57 | 257 |
258 =cut |