#! / usr / bin / perl
use strict;
use warnings;
use LWP :: UserAgent;
# This is the file that will be sent
my $ file = './files/some_file.bin';
# This is the URI to send the request to.
my $ uri = 'http://somedomain.com/form/action/script';
# Request object
my $ request = HTTP :: Request-> new ('POST', $ uri);
# Create a separator, because if we do not specify it forcibly, then with $ ua-> request ($ request) it will not be included in the main title
# though, you can simply make $ request-> as_string after forming the header object, then it will be substituted by default, but we will not risk
my $ boundary = 'X';
my @rand = ('a' .. 'z', 'A' .. 'Z');
for (0..14) {$ boundary. = $ rand [rand (@rand)];}
# Create a title:
$ request-> header ('Content-Type' => 'multipart / form-data; boundary ='. $ boundary);
$ request-> header ('User-Agent' => '<i> Mozilla Firefox 5.0: -) </ i>');
$ request-> header ('Referer' => '<i> http://somedomain.com/form </ i>');
$ request-> protocol ('HTTP / 1.0'); # Although it will make LWP :: UserAgent, but better immediately
# Formation of ordinary, textual form parameters
my $ field = HTTP :: Message-> new (
[
'Content-Disposition' => 'form-data; name = "<i> fieldname </ i>" ',
'Content-Type' => 'text / plain; charset = utf-8 ',
]); # The HTTP header :: Headers is substituted during the creation of the HTTP :: Message object
$ field-> add_content_utf8 ('<i> somevalue </ i>'); # As you can see, somevalue should be in UTF-8
$ request-> add_part ($ field);
# ... And so on, for each text field ...
# Formation of binary form parameters
open (my $ fh, '<', $ file);
# And you can first make a header, and then apply to HTTP :: Message
my $ size = (stat $ file) [7];
my $ header = HTTP :: Headers-> new;
$ header-> header ('Content-Disposition' => 'form-data; name = "<i> file </ i>"; filename = "<i> somefile.bin </ i>'); # Although filename can be calculated from the file name
$ header-> header ('Content-Type' => '<i> application / octet-stream </ i>'); # Or appropriate file type
my $ file_content = HTTP :: Message-> new ($ header);
$ file_content-> add_content ($ _) while <$ fh>;
$ request-> add_part ($ file_content);
close $ fh;
# ... And so on, for each file ...
my $ response = $ ua-> request ($ request);
if ($ response-> is_success) {
print $ response-> content
} else {
die $ response-> status_line
} #! / usr / bin / perl
use strict;
use warnings;
use HTTP :: Headers;
use HTTP :: Message;
use HTTP :: Request;
use HTTP :: Response;
use IO :: Socket :: INET;
# This is the file that will be sent
my $ file = './files/some_file.bin';
# This is the URI to send the request to.
my $ uri = 'http://somedomain.com/form/action/script';
# Since we will use a socket, we need a domain, port and path separately
my ($ domain, $ port, $ path) = $ uri = ~ m / ^ (?: https? \: \ / \ /)? ([^ \ / \:] +) (?: \: (\ d + ))? (. +) $ /;
$ port || = 80; # Default
# A bicycle is, of course, good, but you can easily form headers and non-binary request body using a ready-made module
my $ header = HTTP :: Headers-> new; $ header-> header ('Content-Type' => 'multipart / form-data');
my $ request = HTTP :: Request-> new ('POST', $ uri, $ header); # Instead of $ path we have $ uri, so it should be ;-)
$ request-> protocol ('HTTP / 1.0'); # It is strange that the default protocol does not set the HTTP :: Request protocol, therefore we set ourselves
# For small amounts of data, such as text fields, the bike will also be superfluous
# (SFCI) Conditions are the same as in the previous code (1)
my $ field = HTTP :: Message-> new (
[
'Content-Disposition' => 'form-data; name = "<i> fieldname </ i>" ',
'Content-Type' => 'text / plain; charset = utf-8 ',
]);
$ field-> add_content_utf8 ('<i> somevalue </ i>'); # And here, too, utf8
$ request-> add_part ($ field);
# ... And so on, for each text field ...
Further, our request, but without the files we divide into the main title and the first part of the content
# We divide the regular expression for $ request-> headers-> as_string does not return the first line of the request, namely, the POST command,
# and collect the string yourself, you can of course, but laziness.
my ($ head, $ content) = $ request-> as_string = ~ m / ^ (. +?) \ n \ n (. +) $ / s;
Content is not finished here, so we cut off - [LF] [EOF]
$ content = substr ($ content, 0, -4);
# as well as the boundary
$ content = ~ s / (\ - \ - [^ \ n] +) $ // s;
my $ boundary = $ 1;
# We consider the preliminary length of the request
my $ length = length $ content;
# Now our files:
my $ files = [];
my $ size = (stat $ file) [7];
my $ f_header = HTTP :: Headers-> new;
$ f_header-> header ('Content-Disposition' => 'form-data; name = "<i> file </ i>"; filename = "<i> somefile.bin </ i>');
$ f_header-> header ('Content-Type' => '<i> application / octet-stream </ i>');
$ f_header = $ boundary. "\ n". $ f_header-> as_string. "\ n";
# We arrive at the length of the request
$ length + = length $ f_header;
$ length + = $ size;
# Actually, the procedure below is only for cases when there are many files.
# Then, we first need to calculate the length of the content, because it (the length) will be indicated in the main title
push @ {$ files}, {header => $ f_header, file => $ file};
# ... And so on, for each file ...
# So we have everything ready
$ length + = length $ boundary .'-- '; # The end line is also considered
# Open the socket
my $ socket = IO :: Socket :: INET-> new ($ domain. ':'. $ port) || die $ !;
# To the main title is long
$ head. = "\ nContent-Length:". $ length;
# Send the header and the first (text) part of the content to the socket
print $ socket $ head;
print $ socket "\ n \ n";
print $ socket $ content;
foreach my $ file (@ {$ files}) {
print $ socket $ file -> {header};
open (my $ fh, '<', $ file -> {file});
print $ socket $ _ while <$ fh>;
print $ socket "\ n";
close $ fh;
}
# Send socket end of file
print $ socket $ boundary .'-- ';
# Send socket end of file
shutdown ($ socket, 1);
# Get the answer from the socket and parse it
my $ response = HTTP :: Response-> parse (join ('', <$ socket>));
if ($ response-> is_success) {
print $ response-> content
} else {
die $ response-> status_line
}
Well done (SFCI) I want to note that everything in the code in italics should be replaced with the corresponding values ​​of the problem condition. Note: SFCI - Special for copipaster's idiots. No comments.Source: https://habr.com/ru/post/63432/
All Articles