Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

How do I make a multipart/mixed request (for REST API) in Perl?

by YenForYang (Beadle)
on Nov 28, 2017 at 13:41 UTC ( [id://1204434]=perlquestion: print w/replies, xml ) Need Help??

YenForYang has asked for the wisdom of the Perl Monks concerning the following question:

I'm having difficulty finding any sort of module or documentation on making multipart/mixed requests. Note this is not for sending an email--I'm trying to use the Google Drive v3 REST API, specifically the batch request (see below).

There is an non-Perl "example" given by Google on the Batching Requests page:

Example batch request

POST https://www.googleapis.com/batch

Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.20.0 (gzip)
Content-Type: multipart/mixed; boundary=END_OF_PART
Content-Length: 963

--END_OF_PART Content-Length: 337 Content-Type: application/http content-id: 1 content-transfer-encoding: binary

POST https://www.googleapis.com/drive/v3/files/<var class="apiparam">fileId</var>/permissions?fields=id Authorization: Bearer <var class="apiparam">authorization_token</var> Content-Length: 70 Content-Type: application/json; charset=UTF-8

{ "emailAddress":"example@appsrocks.com", "role":"writer", "type":"user" } --END_OF_PART Content-Length: 353 Content-Type: application/http content-id: 2 content-transfer-encoding: binary

POST https://www.googleapis.com/drive/v3/files/<var class="apiparam">fileId</var>/permissions?fields=id&sendNotificationEmail=false Authorization: Bearer <var class="apiparam">authorization_token</var> Content-Length: 58 Content-Type: application/json; charset=UTF-8

{ "domain":"appsrocks.com", "role":"reader", "type":"domain" } --END_OF_PART--

For example, I want to be able to use these specific calls to update/delete a permission (using PATCH or DELETE semantics) using batch requests:

Permissions: Update

Permissions: Delete

P.S. does anyone know if some key-value pairs can be unspecified--Content-Length, for example, in the above request

  • Comment on How do I make a multipart/mixed request (for REST API) in Perl?

Replies are listed 'Best First'.
Re: How do I make a multipart/mixed request (for REST API) in Perl?
by Your Mother (Archbishop) on Nov 28, 2017 at 15:58 UTC

    You are going to have to do heavy lifting here still, with the auth/authz steps and managing the tokens and the user agent and the actual requests and response parsing, but this should get you over your first hurdle–

    #!/usr/bin/env perl use strictures; use HTTP::Request::Common; use JSON; use URI; my $endpoint = URI->new("https://www.googleapis.com/batch"); my %writer = ( emailAddress => 'example@appsrocks.com', role => "writer", type => "user" ); my %domain = ( reader => "appsrocks.com", role => "reader", type => "domain" ); my $request1 = POST "https://some.uri/you/must/construct", Authorization => "Bearer MOOOOOOOKEN", Content_Type => "application/json; charset=UTF-8", Content => encode_json(\%writer); my $request2 = POST "https://some.uri/you/must/also/construct", Authorization => "Bearer MOOOOOOOKEN", Content_Type => "application/json; charset=UTF-8", Content => encode_json(\%domain); my $top = POST $endpoint, Accept => "gzip", User_Agent => "YourMomsCooking/0.00001"; $top->add_part( $request1, $request2 ); # Here, you would pass the request to a WWW::Mechanize object or somes +uch. print $top->as_string;

    Related reading: HTTP::Request::Common, URI, JSON, HTTP::Message, and WWW::Mechanize. (Update: added URI refs.)

      Points me to exactly what I was looking for, thanks.

      My thanks to everyone else who replied to this node, they were all helpful.

        It's an interesting question and topic. I hope if you get it working to your satisfaction you will come back and post it as a Cool Uses for Perl or on the Google forums or github or anywhere others can benefit from your initiative in making the API work with Perl.

      Thank you for pointing out the proper way to do this! We should have some documentation updates coming in the next release of HTTP::Message.

      A pull request to get things started has been entered.

      Thanks again!
Re: How do I make a multipart/mixed request (for REST API) in Perl?
by genio (Beadle) on Nov 28, 2017 at 15:57 UTC

    EDIT: I'm an idiot and as the other reply here shows, HTTP::Message already has this functionality built-in. ->add_part() is your friend. I should have looked a bit harder.

    OK, so what you're looking for I haven't yet found on the CPAN. This is _completely_ untested, so please take it with a grain of salt (or 100 such grains).

    You can create multiple HTTP::Request objects (get, post, etc). You can then group them all together in one new HTTP::Request object with a fairly simple function like I'm showing below and then just send that request:

    use UUID qw(uuid); use HTTP::Request (); use Encode (); sub build_multi { my ($method, $uri, $header, @requests) = @_; my $r = HTTP::Request->new($method, $uri, $header); my $boundary = uuid(); $r->header( 'Content-Type' => "multipart/mixed; boundary=$boundary" ); my $content = ''; for my $req (@requests) { $content .= $r->as_string("\015\012"); $content .= "\015\012--{$boundary}"; } $content .= '--' if $content; $r->content( Encode::encode_utf8($content) ); return $r }

    AGAIN: completely untested

      You're not an idiot at all. The information was buried in one of the sub-sub packages that drive this stuff. I mostly do web work and I didn't know it off the top of my head. I had to track it down and I found a couple nearly identical unanswered questions before realizing the answer wasn't in, or reflected up to, the most intuitive places.

      Yup ... no matter what it is, it is always "built-in" somewhere in CPAN!

        This is simply untrue; an increasingly sad situation that takes enthusiastic devs and the support of the community—in other words, don’t push using an existing tool in another language if someone is interested in building it in Perl—to ameliorate. There are fields where the CPAN has not kept pace. Raw/plain HTTP-oriented stuff, however, is not one of them because this part of the technology hasn't changed much in a couple of decades.

Re: How do I make a multipart/mixed request (for REST API) in Perl?
by 1nickt (Canon) on Nov 28, 2017 at 14:56 UTC

    Hi, I had a bit of a look around as the technique of batching API calls into a single HTTP request sounds very useful. I couldn't find anything: HTTP::Request::Common has support for multipart/form-data (for uploading files) but the content-type is hard-coded.

    You could probably work something up, wrapping a bunch of HTTP::Request requests ->as_string() in an ecompassing request, given that according to the Google doc, the parts are each a complete nested request.

    Hope this helps!


    The way forward always starts with a minimal test.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1204434]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (2)
As of 2024-04-25 06:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found