Applied spelling fix from comment on RT #106386
[catagits/Catalyst-Runtime.git] / lib / Catalyst / UTF8.pod
index b32bc31..044a573 100644 (file)
@@ -196,6 +196,27 @@ to send over the wire via HTTP needs to be bytes (not unicode characters).
 Remember if you use any utf8 literals in your source code, you should use the
 C<use utf8> pragma.
 
+B<NOTE:> Assuming UTF-8 in your query parameters and keywords may be an issue if you have
+legacy code where you created URL in templates manually and used an encoding other than UTF-8.
+In these cases you may find versions of Catalyst after 5.90080+ will incorrectly decode.  For
+backwards compatibility we offer three configurations settings, here described in order of
+precedence:
+
+C<do_not_decode_query>
+
+If true, then do not try to character decode any wide characters in your
+request URL query or keywords.  You will need to handle this manually in your action code
+(although if you choose this setting, chances are you already do this).
+
+C<default_query_encoding>
+
+This setting allows one to specify a fixed value for how to decode your query, instead of using
+the default, UTF-8.
+
+C<decode_query_using_global_encoding>
+
+If this is true we decode using whatever you set C<encoding> to.
+
 =head2 UTF8 in Form POST
 
 In general most modern browsers will follow the specification, which says that POSTed
@@ -254,6 +275,49 @@ based tricks and workarounds for even more odd cases (just search the web for th
 a number of approaches.  Hopefully as more compliant browsers become popular these edge cases
 will fade.
 
+B<NOTE>  It is possible for a form POST multipart response (normally a file upload) to contain
+inline content with mixed content character sets and encoding.  For example one might create
+a POST like this:
+
+    use utf8;
+    use HTTP::Request::Common;
+
+    my $utf8 = 'test ♥';
+    my $shiftjs = 'test テスト';
+    my $req = POST '/root/echo_arg',
+        Content_Type => 'form-data',
+          Content =>  [
+            arg0 => 'helloworld',
+            Encode::encode('UTF-8','♥') => Encode::encode('UTF-8','♥♥'),
+            arg1 => [
+              undef, '',
+              'Content-Type' =>'text/plain; charset=UTF-8',
+              'Content' => Encode::encode('UTF-8', $utf8)],
+            arg2 => [
+              undef, '',
+              'Content-Type' =>'text/plain; charset=SHIFT_JIS',
+              'Content' => Encode::encode('SHIFT_JIS', $shiftjs)],
+            arg2 => [
+              undef, '',
+              'Content-Type' =>'text/plain; charset=SHIFT_JIS',
+              'Content' => Encode::encode('SHIFT_JIS', $shiftjs)],
+          ];
+
+In this case we've created a POST request but each part specifies its own content
+character set (and setting a content encoding would also be possible).  Generally one
+would not run into this situation in a web browser context but for completeness sake
+Catalyst will notice if a multipart POST contains parts with complex or extended
+header information.  In these cases we will try to inspect the meta data and do the
+right thing (in the above case we'd use SHIFT_JIS to decode, not UTF-8).  However if
+after inspecting the headers we cannot figure out how to decode the data, in those cases it
+will not attempt to apply decoding to the form values.  Instead the part will be represented as
+an instance of an object L<Catalyst::Request::PartData> which will contain all the header 
+information needed for you to perform custom parser of the data.
+
+Ideally we'd fix L<Catalyst> to be smarter about decoding so please submit your cases of
+this so we can add intelligence to the parser and find a way to extract a valid value out
+of it.
+
 =head1 UTF8 Encoding in Body Response
 
 When does L<Catalyst> encode your response body and what rules does it use to
@@ -404,6 +468,11 @@ B<NOTE> If you try to change the encoding after you start the stream, this will
 response.  However since you've already started streaming this will not show up as an HTTP error
 status code, but rather error information in your body response and an error in your logs.
 
+B<NOTE> If you use ->body AFTER using ->write (for example you may do this to write your HTML
+HEAD information as fast as possible) we expect the contents to body to be encoded as it
+normally would be if you never called ->write.  In general unless you are doing weird custom
+stuff with encoding this is likely to just already do the correct thing.
+
 The second way to stream a response is to get the response writer object and invoke methods
 on that directly:
 
@@ -427,7 +496,7 @@ L<http://www.catalystframework.org/calendar/2013/12>, L<http://www.catalystframe
 L<http://www.catalystframework.org/calendar/2013/14>.
 
 The main difference this year is that previously calling ->write_fh would return the actual
-L<Plack> writer object that was supplied by your plack application handler, whereas now we wrap
+L<Plack> writer object that was supplied by your Plack application handler, whereas now we wrap
 that object in a lightweight decorator object that proxies the C<write> and C<close> methods
 and supplies an additional C<write_encoded> method.  C<write_encoded> does the exact same thing
 as C<write> except that it will first encode the string when necessary.  In general if you are
@@ -558,10 +627,17 @@ so you can disable this with the following configurations setting:
 
 Where C<MyApp> is your L<Catalyst> subclass.
 
+If you do not wish to disable all the Catalyst encoding features, you may disable specific
+features via two additional configuration options:  'skip_body_param_unicode_decoding'
+and 'skip_complex_post_part_handling'.  The first will skip any attempt to decode POST
+parameters in the creating of body parameters and the second will skip creation of instances
+of L<Catalyst::Request::PartData> in the case that the multipart form upload contains parts
+with a mix of content character sets.
+
 If you believe you have discovered a bug in UTF8 body encoding, I strongly encourage you to
 report it (and not try to hack a workaround in your local code).  We also recommend that you
 regard such a workaround as a temporary solution.  It is ideal if L<Catalyst> extension
-authors can start to count on L<Catalyst> doing the write thing for encoding
+authors can start to count on L<Catalyst> doing the right thing for encoding.
 
 =head1 Conclusion