Toby Inkster avatar Toby Inkster committed 6d47589

examples of posting data

Comments (0)

Files changed (2)

examples/form-data.pl

+use Web::Magic;
+
+Web::Magic
+	-> new("http://example.com/")
+	-> POST([Foo => 1, Bar => 2, Foo => 'xYzZY'])
+	-> Content_Type('multipart/form-data')
+	-> tap( sub { print $_->_final_request_object->as_string } )
+	-> cancel;

lib/Web/Magic/Examples.pod

 
 Arguably this takes chaining too far. ;-)
 
+=head2 POSTing data
+
+A cool thing about Web::Magic is that it will happily accept references,
+even blessed objects, as body data for HTTP POST, PUT, etc requests. How
+exactly that is serialized depends on what sort of reference you've
+given it, and what request Content-Type header you set.
+
+"application/x-www-form-urlencoded" (yes, that's a horrible name) is the
+most commonly used content type. It's the default for HTML form submissions.
+It's basically a bunch of key-value pairs, but unlike Perl hashes, keys
+may be repeated. You can submit this format using:
+
+  web <http://example.com/>
+    -> POST({ key1 => 'value1', key2 => 'value2' })
+    -> Content_Type('application/x-www-form-urlencoded');
+
+Though that's the default Content-Type, so you don't need to set it
+explicitly.
+
+  web <http://example.com/>
+    -> POST({ key1 => 'value1', key2 => 'value2' });
+
+You may pass an arrayref instead of a hashref. (This helps if you need to
+repeat a key.)
+
+  web <http://example.com/>
+    -> POST([ key1 => 'value1', key2 => 'value2' ]);
+
+Most web browsers do support another media type for POSTing data:
+"multipart/form-data". This has an advantage over
+"application/x-www-form-urlencoded" in that it allows file uploads.
+To use "multipart/form-data", you need to specify the Content-Type
+explicitly.
+
+  web <http://example.com/>
+    -> POST([ key1 => 'value1', key2 => 'value2' ])
+    -> Content_Type('multipart/form-data');
+
+As per "application/x-www-form-urlencoded", you may supply either a
+hashref or arrayref.
+
+Note how so far all values have been simple scalars; to upload a file,
+your value must be an arrayref. The first element of the array is
+required. It is the filename of the file to read data from. The second
+(optional) element of the array if the filename you want to provide to
+the server. Further elements are treated as key=>value pairs which set
+additional headers for the uploaded file. (Each uploaded file has its
+own set of headers.) The most useful header to set is Content-Type.
+
+  my @upload = ('/etc/motd', 'motd.txt', Content_Type => 'text/plain');
+  web <http://example.com/>
+    -> POST([ key1 => 'value1', key2 => \@upload ])
+    -> Content_Type('multipart/form-data');
+ 
+A future version of Web::Magic will hopefully add more flexibility, such
+as the ability to pass a file handle.
+
+While "application/x-www-form-urlencoded" and "multipart/form-data" are
+common, HTTP does allow arbitrary media types to be POSTed. Here's an
+example of POSTing "text/plain":
+
+  web <http://example.com/>
+    -> POST("Hello world!\n")
+    -> Content_Type('text/plain');
+
+Note that this is not the same as uploading a plain text file using
+"multipart/form-data". Only POST types other than the "big two" if you
+know that you're definitely supposed to.
+
+As per the "text/plain" example above, the general pattern is that you
+supply the HTTP body as a simple string. However, for certain content
+types, you can supply hashrefs, arrayrefs or blessed objects.
+
+=over
+
+=item * ARRAY: C<< application/json >> or C<< text/x-yaml >>.
+
+=item * HASH: C<< application/json >> or C<< text/x-yaml >>.
+
+=item * L<XML::LibXML::Node>: C<< application/xml >>, C<< text/xml >>, other XML media types, and C<< text/html >>.
+
+=item * L<RDF::Trine::Model>: C<< application/rdf+xml >>, C<< text/turtle >>, C<< text/plain >>, C<< text/x-nquads >>, C<< application/json >>.
+
+=back
+
+Here's a simple Atom Publishing Protocol example, taking the first entry
+from a local Atom feed, and POSTing it to an APP collection.
+
+  my $dom   = XML::LibXML->load_xml(location => 'file.atom');
+  my $entry = $dom->getElementsByTagName('entry')->[0];
+  web <http://example.com/app/>
+    -> POST($entry)
+    -> Content_Type('application/atom+xml; type=entry')
+    -> Slug($entry->getElementsByTagName('title')->[0]->textContent);
+
+Of course, the C<POST> method is nothing special. All of this works with
+other HTTP methods too, such as C<PUT>. However for some HTTP methods
+such as C<GET> and C<HEAD> it is highly unusual (though permissible) to
+include a request body.
+
 =head1 SEE ALSO
 
 L<Web::Magic>.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.