summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon duSaint2023-09-12 09:20:42 -0700
committerJon duSaint2023-09-12 09:20:42 -0700
commit4793b53fafde382fb3383d4d0f2f5fcccb1a8e41 (patch)
tree6e16aeb39558b0118bd80f0d2cb9349260586be6
parent4db96025565959c86ba797021c6199af9f62f194 (diff)

Reolink.pm: Support HTTPS

Newer Reolink firmware supports HTTPS and ships with HTTP API access disabled by default. Switch to LWP::UserAgent for HTTPS support and redirect to HTTPS if needed.

-rw-r--r--reolink/Reolink.pm35
1 files changed, 24 insertions, 11 deletions
diff --git a/reolink/Reolink.pm b/reolink/Reolink.pm
index 0bc8e19..5ce5bbd 100644
--- a/reolink/Reolink.pm
+++ b/reolink/Reolink.pm
@@ -27,21 +27,28 @@ use warnings;
use Carp;
use Data::Dumper;
-use HTTP::Tiny;
+use HTTP::Request;
+use IO::Socket::SSL;
use JSON;
+use LWP::UserAgent;
-our $VERSION = '1.0';
+our $VERSION = '1.1';
# Reolink defaults
my ($default_user, $default_pass, $default_proto) = ('admin', '', 'http');
+sub make_url {
+ my $this = shift;
+ $this->{url} = "$this->{proto}://$this->{host}/cgi-bin/api.cgi";
+}
+
# Internal function to actually invoke the API
sub api {
my ($this, %args) = @_;
unless ($this->{http}) {
- $this->{http} = HTTP::Tiny->new (agent => "Reolink/$VERSION",
- default_headers => {"Content-Type" => "application/json"});
+ $this->{http} = LWP::UserAgent->new (agent => "Reolink/$VERSION");
+ $this->{http}->ssl_opts (SSL_verify_mode => SSL_VERIFY_NONE, verify_hostname => 0);
}
my $json = { cmd => $args{cmd} };
@@ -52,13 +59,19 @@ sub api {
my $token = $this->{token} // 'null';
my $url = "$this->{url}?cmd=$args{cmd}&token=$token";
+ my $req = HTTP::Request->new ('POST', $url, ['Content-Type' => 'application/json', 'Accept' => 'application/json'], encode_json ([$json]));
- my $resp = $this->{http}->request ('POST', $url, {content => encode_json ([$json])});
+ my $resp = $this->{http}->request ($req);
+ if ($resp->is_redirect && $this->{proto} eq 'http') {
+ $this->{proto} = 'https';
+ make_url ($this);
+ return api ($this, %args);
+ }
- my $ret = $resp->{success} ? $resp->{content} : '[{"code":-1}]';
+ my $ret = $resp->is_success ? $resp->decoded_content : '[{"code":-1}]';
my $retref = decode_json ($ret);
- carp "Request for command '$args{cmd} failed" unless $resp->{success};
+ carp "Request for command '$args{cmd} failed" unless $resp->is_success;
return $retref->[0];
}
@@ -90,7 +103,7 @@ sub new {
token => undef,
errors => 0
};
- $this->{url} = "$this->{proto}://$this->{host}/cgi-bin/api.cgi";
+ make_url ($this);
bless $this, $class;
}
@@ -512,9 +525,9 @@ sub Snap {
my @valid = ("A".."Z", "a".."z", "0".."9", "-", "_");
my $tok = join "", map { $valid[ int (rand (256)) % @valid] } 1..16;
my $url = "$this->{url}?cmd=Snap&channel=0&rs=$tok&token=$this->{token}";
- my $resp = $this->{http}->request ('POST', $url);
+ my $resp = $this->{http}->post ($url);
- unless ($resp->{success}) {
+ unless ($resp->is_success) {
use Data::Dumper;
carp "Failed to take snapshot";
print Dumper $resp;
@@ -528,7 +541,7 @@ sub Snap {
}
binmode $fh;
- print $fh $resp->{content};
+ print $fh $resp->decoded_content;
close $fh;