diff options
| author | Jon duSaint | 2023-09-12 09:20:42 -0700 |
|---|---|---|
| committer | Jon duSaint | 2023-09-12 09:20:42 -0700 |
| commit | 4793b53fafde382fb3383d4d0f2f5fcccb1a8e41 (patch) | |
| tree | 6e16aeb39558b0118bd80f0d2cb9349260586be6 | |
| parent | 4db96025565959c86ba797021c6199af9f62f194 (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.pm | 35 |
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; |
