Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

urlopen method in Perl 6?

Tags:

raku

I'm translating a Python module to Perl 6, but can't find a method called urlopen, which could accept data:

    from six.moves.urllib import request

    req = request.Request(url, headers=headers)

    if headers.get('Content-Type') == 'application/x-www-form-urlencoded':
        data = oauth_query(args, via='quote_plus', safe='').encode()

    elif 'form-data' in headers.get('Content-Type', ''):  # multipart/form-data
        data = args['form-data']
    else:
        data = None

    resp = request.urlopen(req, data=data)
    resp.json = lambda: json.loads(resp.read().decode() or '""')
    return resp

oauth_query is a method that return a sorted string:

def oauth_query(args, via='quote', safe='~'):
    return '&'.join('%s=%s' % (k, oauth_escape(v, via, safe)) for k, v in sorted(args.items()))

I translate the above code to Perl 6:

   use WWW;

   my $data = "";
   if %headers{'Content-Type'} eq 'application/x-www-form-urlencoded' {
       $data = oauth_query(%args);
   } elsif %headers{'Content-Type'}.contains('form-data') {
       $data = %args{'form-data'};
   } else {
       $data = Any;
   }

   my $res = get $url, |%headers; # but without data that contains Content-Type, it will
                                  # Died with HTTP::MediaType::X::MediaTypeParser::IllegalMediaType

I want to return a resp as in Python. Any help is welcome!

like image 683
chenyf Avatar asked Apr 06 '18 10:04

chenyf


2 Answers

use Cro::HTTP::Client;

my $resp;
my $data = "";

if (%headers{'content-type'} // '') eq self.form_urlencoded {
    $data = oauth_query(%args);
} elsif (%headers{'content-type'} // '').contains('form-data') { # multipart/form-data
    $data = %args{'form-data'};
} else {
    $data = "";
}

my $client = Cro::HTTP::Client.new(headers =>  |%headers);

if $data {
    $resp = await $client.post: $url, body => |%args;
} else {
    $resp = await $client.get: $url;
}

return $resp;
like image 44
chenyf Avatar answered Sep 24 '22 00:09

chenyf


I have reduced the program to the bare minimum; you will still have to take care of headers and the OAuth query, but this works

use WWW;

sub MAIN( :$have-data = 0 ) {
    my $url='https://jsonplaceholder.typicode.com/posts/';
    my %args=%(form-data => "userId=1&id=2");
    my $data = "";

    if $have-data {
        $data = %args{'form-data'};
    } 

    my $res;
    if $data {
        $res = post $url, $data;
    } else {
        $res= get $url~'1';
    }
    say $res;
}

Baseline is that urlopen in Python does get or post depending on whether there is data or not. In this case, I use a simple if for that purpose, since WWW is quite barebones and does not support that. I am using also a mock REST interface, so I have actually to change the URL depending on the data, which is also dummy data. You can call the program either with no argument or with

perl6 urlopen.p6 --have-data=1

and the mock server will return... something. It would be great if you contributed a module with a (somewhat) higher level than WWW, or to WWW itself. Hope this solves (kinda) your problem.

like image 81
jjmerelo Avatar answered Sep 24 '22 00:09

jjmerelo