When from_psgi_response, a bug when headers are already output and charset is set...
[catagits/Catalyst-Runtime.git] / t / psgi_utils.t
1 use warnings;
2 use strict;
3
4 # Make it easier to mount PSGI apps under catalyst
5
6 my $psgi_app = sub {
7   my $req = Plack::Request->new(shift);
8   return [200,[],[$req->path]];
9 };
10
11 {
12   package MyApp::PSGIObject;
13
14   sub as_psgi {
15     return [200, ['Content-Type' => 'text/plain'], ['as_psgi']];
16   };
17
18   package MyApp::Controller::Docs;
19   $INC{'MyApp/Controller/Docs.pm'} = __FILE__;
20
21   use base 'Catalyst::Controller';
22   use Plack::Request;
23   use Catalyst::Utils;
24
25   sub as_psgi :Local {
26     my ($self, $c) = @_;
27     my $as_psgi = bless +{}, 'MyApp::PSGIObject';
28     $c->res->from_psgi_response($as_psgi);
29   }
30
31   sub name :Local {
32     my ($self, $c) = @_;
33     my $env = $c->Catalyst::Utils::env_at_action;
34     $c->res->from_psgi_response(
35       $psgi_app->($env));
36
37   }
38
39   sub name_args :Local Args(1) {
40     my ($self, $c, $arg) = @_;
41     my $env = $c->Catalyst::Utils::env_at_action;
42     $c->res->from_psgi_response(
43       $psgi_app->($env));
44   }
45
46   sub filehandle :Local {
47     my ($self, $c, $arg) = @_;
48     my $path = File::Spec->catfile('t', 'utf8.txt');
49     open(my $fh, '<', $path) || die "trouble: $!";
50     $c->res->from_psgi_response([200, ['Content-Type'=>'text/html'], $fh]);
51   }
52
53   sub direct :Local {
54     my ($self, $c, $arg) = @_;
55     $c->res->from_psgi_response([200, ['Content-Type'=>'text/html'], ["hello","world"]]);
56   }
57
58   sub streaming_body :Local {
59     my ($self, $c) = @_;
60     my $psgi_app = sub {
61         my $respond = shift;
62         my $writer = $respond->([200,["Content-Type" => "text/plain"]]);
63         $writer->write("body");
64         $writer->close;
65     };
66     $c->res->from_psgi_response($psgi_app);
67   }
68   sub streaming_body_with_charset :Local {
69     my ($self, $c) = @_;
70     my $psgi_app = sub {
71         my $respond = shift;
72         my $writer = $respond->([200,["Content-Type" => "text/plain; charset=utf-8"]]);
73         $writer->write("body");
74         $writer->close;
75     };
76     $c->res->from_psgi_response($psgi_app);
77   }
78
79   package MyApp::Controller::User;
80   $INC{'MyApp/Controller/User.pm'} = __FILE__;
81
82   use base 'Catalyst::Controller';
83   use Plack::Request;
84   use Catalyst::Utils;
85
86   sub local_example :Local {
87     my ($self, $c) = @_;
88     my $env = $self->get_env($c);
89     $c->res->from_psgi_response(
90       $psgi_app->($env));
91   }
92
93   sub local_example_args1 :Local Args(1) {
94     my ($self, $c) = @_;
95     my $env = $self->get_env($c);
96     $c->res->from_psgi_response(
97       $psgi_app->($env));
98   }
99
100   sub path_example :Path('path-example') {
101     my ($self, $c) = @_;
102     my $env = $self->get_env($c);
103     $c->res->from_psgi_response(
104       $psgi_app->($env));
105   }
106
107   sub path_example_args1 :Path('path-example-args1') {
108     my ($self, $c) = @_;
109     my $env = $self->get_env($c);
110     $c->res->from_psgi_response(
111       $psgi_app->($env));
112   }
113
114   sub chained :Chained(/) PathPrefix CaptureArgs(0) { }
115
116     sub from_chain :Chained('chained') PathPart('') CaptureArgs(0) {}
117
118       sub end_chain :Chained('from_chain') PathPath(abc-123) Args(1)
119       {
120         my ($self, $c) = @_;
121         my $env = $self->get_env($c);
122         $c->res->from_psgi_response(
123           $psgi_app->($env));
124       }
125
126   sub mounted :Local Args(1) {
127     my ($self, $c, $arg) = @_;
128     our $app ||= ref($c)->psgi_app;
129     my $env = $self->get_env($c);
130     $c->res->from_psgi_response(
131       $app->($env));
132   }
133
134   sub mount_arg :Path(/mounted) Arg(1) {
135     my ($self, $c, $arg) = @_;
136     my $uri =  $c->uri_for( $self->action_for('local_example_args1'),$arg);
137     $c->res->body("$uri");
138   }
139
140   sub mount_noarg :Path(/mounted_no_arg)  {
141     my ($self, $c) = @_;
142     my $uri =  $c->uri_for( $self->action_for('local_example_args1'),444);
143     $c->res->body("$uri");
144   }
145
146
147   sub get_env {
148     my ($self, $c) = @_;
149     if($c->req->query_parameters->{path_prefix}) {
150       return $c->Catalyst::Utils::env_at_path_prefix;
151     } elsif($c->req->query_parameters->{env_path}) {
152       return $c->Catalyst::Utils::env_at_action;
153     } elsif($c->req->query_parameters->{path}) {
154       return $c->Catalyst::Utils::env_at_request_uri;
155     } else {
156       return $c->req->env;
157     }
158   }
159
160   package MyApp;
161   use Catalyst;
162   MyApp->setup;
163
164 }
165
166 use Test::More;
167 use Catalyst::Test 'MyApp';
168
169 {
170   my ($res, $c) = ctx_request('/docs/as_psgi');
171   is $res->content, 'as_psgi';
172 }
173
174 {
175   my ($res, $c) = ctx_request('/user/mounted/111?path_prefix=1');
176   is $c->action, 'user/mounted';
177   is $res->content, 'http://localhost/user/user/local_example_args1/111';
178   is_deeply $c->req->args, [111];
179 }
180
181 {
182   my ($res, $c) = ctx_request('/user/mounted/mounted_no_arg?env_path=1');
183   is $c->action, 'user/mounted';
184   is $res->content, 'http://localhost/user/mounted/user/local_example_args1/444';
185   is_deeply $c->req->args, ['mounted_no_arg'];
186 }
187
188 # BEGIN [user/local_example]
189 {
190   my ($res, $c) = ctx_request('/user/local_example');
191   is $c->action, 'user/local_example';
192   is $res->content, '/user/local_example';
193   is_deeply $c->req->args, [];
194 }
195
196 {
197   my ($res, $c) = ctx_request('/user/local_example/111/222');
198   is $c->action, 'user/local_example';
199   is $res->content, '/user/local_example/111/222';
200   is_deeply $c->req->args, [111,222];
201 }
202
203 {
204   my ($res, $c) = ctx_request('/user/local_example?path_prefix=1');
205   is $c->action, 'user/local_example';
206   is $res->content, '/local_example';
207   is_deeply $c->req->args, [];
208 }
209
210 {
211   my ($res, $c) = ctx_request('/user/local_example/111/222?path_prefix=1');
212   is $c->action, 'user/local_example';
213   is $res->content, '/local_example/111/222';
214   is_deeply $c->req->args, [111,222];
215 }
216
217 {
218   my ($res, $c) = ctx_request('/user/local_example?env_path=1');
219   is $c->action, 'user/local_example';
220   is $res->content, '/';
221   is_deeply $c->req->args, [];
222 }
223
224 {
225   my ($res, $c) = ctx_request('/user/local_example/111/222?env_path=1');
226   is $c->action, 'user/local_example';
227   is $res->content, '/111/222';
228   is_deeply $c->req->args, [111,222];
229 }
230
231 {
232   my ($res, $c) = ctx_request('/user/local_example?path=1');
233   is $c->action, 'user/local_example';
234   is $res->content, '/';
235   is_deeply $c->req->args, [];
236 }
237
238 {
239   my ($res, $c) = ctx_request('/user/local_example/111/222?path=1');
240   is $c->action, 'user/local_example';
241   is $res->content, '/';
242   is_deeply $c->req->args, [111,222];
243 }
244
245 # END [user/local_example]
246
247 # BEGIN [/user/local_example_args1/***/]
248
249 {
250   my ($res, $c) = ctx_request('/user/local_example_args1/333');
251   is $c->action, 'user/local_example_args1';
252   is $res->content, '/user/local_example_args1/333';
253   is_deeply $c->req->args, [333];
254 }
255
256 {
257   my ($res, $c) = ctx_request('/user/local_example_args1/333?path_prefix=1');
258   is $c->action, 'user/local_example_args1';
259   is $res->content, '/local_example_args1/333';
260   is_deeply $c->req->args, [333];
261 }
262
263 {
264   my ($res, $c) = ctx_request('/user/local_example_args1/333?env_path=1');
265   is $c->action, 'user/local_example_args1';
266   is $res->content, '/333';
267   is_deeply $c->req->args, [333];
268 }
269
270 {
271   my ($res, $c) = ctx_request('/user/local_example_args1/333?path=1');
272   is $c->action, 'user/local_example_args1';
273   is $res->content, '/';
274   is_deeply $c->req->args, [333];
275 }
276
277 # END [/user/local_example_args1/***/]
278
279 # BEGIN [/user/path-example]
280
281 {
282   my ($res, $c) = ctx_request('/user/path-example');
283   is $c->action, 'user/path_example';
284   is $res->content, '/user/path-example';
285   is_deeply $c->req->args, [];
286 }
287
288 {
289   my ($res, $c) = ctx_request('/user/path-example?path_prefix=1');
290   is $c->action, 'user/path_example';
291   is $res->content, '/path-example';
292   is_deeply $c->req->args, [];
293 }
294
295 {
296   my ($res, $c) = ctx_request('/user/path-example?env_path=1');
297   is $c->action, 'user/path_example';
298   is $res->content, '/';
299   is_deeply $c->req->args, [];
300 }
301
302 {
303   my ($res, $c) = ctx_request('/user/path-example?path=1');
304   is $c->action, 'user/path_example';
305   is $res->content, '/';
306   is_deeply $c->req->args, [];
307 }
308
309
310 {
311   my ($res, $c) = ctx_request('/user/path-example/111/222');
312   is $c->action, 'user/path_example';
313   is $res->content, '/user/path-example/111/222';
314   is_deeply $c->req->args, [111,222];
315 }
316
317 {
318   my ($res, $c) = ctx_request('/user/path-example/111/222?path_prefix=1');
319   is $c->action, 'user/path_example';
320   is $res->content, '/path-example/111/222';
321   is_deeply $c->req->args, [111,222];
322 }
323
324 {
325   my ($res, $c) = ctx_request('/user/path-example/111/222?env_path=1');
326   is $c->action, 'user/path_example';
327   is $res->content, '/111/222';
328   is_deeply $c->req->args, [111,222];
329 }
330
331 {
332   my ($res, $c) = ctx_request('/user/path-example/111/222?path=1');
333   is $c->action, 'user/path_example';
334   is $res->content, '/';
335   is_deeply $c->req->args, [111,222];
336 }
337
338 {
339   my ($res, $c) = ctx_request('/user/path-example-args1/333');
340   is $c->action, 'user/path_example_args1';
341   is $res->content, '/user/path-example-args1/333';
342   is_deeply $c->req->args, [333];
343 }
344
345 {
346   my ($res, $c) = ctx_request('/user/path-example-args1/333?path_prefix=1');
347   is $c->action, 'user/path_example_args1';
348   is $res->content, '/path-example-args1/333';
349   is_deeply $c->req->args, [333];
350 }
351
352 {
353   my ($res, $c) = ctx_request('/user/path-example-args1/333?env_path=1');
354   is $c->action, 'user/path_example_args1';
355   is $res->content, '/333';
356   is_deeply $c->req->args, [333];
357 }
358
359 {
360   my ($res, $c) = ctx_request('/user/path-example-args1/333?path=1');
361   is $c->action, 'user/path_example_args1';
362   is $res->content, '/';
363   is_deeply $c->req->args, [333];
364 }
365
366 # Chaining test /user/end_chain/*
367 #
368 #
369
370 {
371   my ($res, $c) = ctx_request('/user/end_chain/444');
372   is $c->action, 'user/end_chain';
373   is $res->content, '/user/end_chain/444';
374   is_deeply $c->req->args, [444];
375 }
376
377 {
378   my ($res, $c) = ctx_request('/user/end_chain/444?path_prefix=1');
379   is $c->action, 'user/end_chain';
380   is $res->content, '/end_chain/444';
381   is_deeply $c->req->args, [444];
382 }
383
384 {
385   my ($res, $c) = ctx_request('/user/end_chain/444?env_path=1');
386   is $c->action, 'user/end_chain';
387   is $res->content, '/444';
388   is_deeply $c->req->args, [444];
389 }
390
391 {
392   my ($res, $c) = ctx_request('/user/end_chain/444?path=1');
393   is $c->action, 'user/end_chain';
394   is $res->content, '/';
395   is_deeply $c->req->args, [444];
396 }
397
398 {
399   my ($res, $c) = ctx_request('/docs/name');
400   is $c->action, 'docs/name';
401   is $res->content, '/';
402   is_deeply $c->req->args, [];
403 }
404
405 {
406   my ($res, $c) = ctx_request('/docs/name/111/222');
407   is $c->action, 'docs/name';
408   is $res->content, '/111/222';
409   is_deeply $c->req->args, [111,222];
410 }
411
412 {
413   my ($res, $c) = ctx_request('/docs/name_args/111');
414   is $c->action, 'docs/name_args';
415   is $res->content, '/111';
416   is_deeply $c->req->args, [111];
417 }
418
419 {
420   use utf8;
421   use Encode;
422   my ($res, $c) = ctx_request('/docs/filehandle');
423   is Encode::decode_utf8($res->content), "<p>This is stream_body_fh action ♥</p>\n";
424 }
425
426 {
427   my ($res, $c) = ctx_request('/docs/direct');
428   is $res->content, "helloworld";
429 }
430
431 {
432   my ($res, $c) = ctx_request('/docs/streaming_body');
433   is $res->content, "body";
434 }
435 {
436   my ($res, $c) = ctx_request('/docs/streaming_body_with_charset');
437   is $res->content, "body";
438 }
439
440 done_testing();