NAME
Net::Gemini - a small gemini client
SYNOPSIS
use Net::Gemini;
my ($gem, $code) = Net::Gemini->get('gemini://example.org/');
use Syntax::Keyword::Match;
match($code : ==) {
case(0) { die "request failed " . $gem->error }
case(1) { ... $gem->meta as prompt for input ... }
case(2) { ... $gem->meta and $gem->content and ... }
case(3) { ... $gem->meta as redirect ... }
case(4) { ... $gem->meta as temporary failure ... }
case(5) { ... $gem->meta as permanent failure ... }
case(6) { ... $gem->meta as client certificate message ... }
}
DESCRIPTION
This module implements code that may help implement a gemini client in Perl.
CAVEATS
It's a pretty beta module.
The default SSL verification is more or less to accept the connection; this is perhaps not ideal. The caller will need to implement TOFU or a similar means of verifying the other end.
gemini://makeworld.space/gemlog/2020-07-03-tofu-rec.gmi
METHODS
- get URI [ parameters ... ]
-
Tries to obtain the given gemini URI.
Returns an object and a result code. The socket is set to use the
:raw
binmode. The result code will be0
if there was a problem with the request--that the URI failed to parse, or the connection failed--or otherwise a gemini code in the range of1
to6
inclusive, which will indicate the next steps any subsequent code should take.For code
2
responses the response body may be split between content and whatever remains unread in the socket, if anything.Parameters include:
- bufsize => strictly-positive-integer
-
Size of buffer to use for requests, 4096 by default. Note that a naughty server may return data in far smaller increments than this.
- early_shutdown => boolean
-
If true, attempts an early shutdown of the SSL connection after the request is sent. This fiddles with the internal state of IO::Socket::SSL as the
shutdown
call does not appear to be exposed outside the module.Use with caution.
- ssl => { params }
-
Passes the given parameters to the IO::Socket::SSL constructor. These could be used to configure e.g. the
SSL_verify_mode
or to set a verification callback, or to specify a custom SNI host viaSSL_hostname
. - tofu => boolean
-
If true, only the leaf certificate will be checked. Otherwise, the full certificate chain will be verified by default, which is probably not what you want when trusting the very first leaf certificate seen.
Also with this flag set hostname verification is turned off; the caller can manage
SSL_verifycn_scheme
and possiblySSL_verifycn_name
via the ssl param if this needs to be customized. - verify_ssl => code-reference
-
Custom callback function to handle SSL verification. The default is to accept the connection (Trust On All Uses), which is perhaps not ideal. The callback function is passed the host, port, certificate digest, and certificate expiration date (compatible with DateTime::Format::RFC3339) and should return a
1
to verify the connection, or0
to not....->get( $url, ..., verify_ssl => sub { my ($host, $port, $digest, $not_before, $not_after, $ok, $raw_cert) = @_; return 1 if int rand 2; # certificate is OK return 0; } );
The "okay?" boolean and raw certificate is also passed; these could be used to allow certificates that other code was able to verify, or to perform custom checks on the certificate using probably various routines from Net::SSLeay.
Note that some have argued that under TOFU one should not verify the hostname nor the dates (notBefore, notAfter) of the certificate, only to accept the first certificate presented as-is, like SSH does, and to use that certificate thereafter. This has plusses and minuses.
- getmore callback [ bufsize => n ]
-
A callback interface is provided to consume the response body, if any. Generally this should only be present for response code
2
. The meta line should be consulted for details on the MIME type and encoding of the bytes;$body
in the following code may need to be decoded.my $body = ''; $gem->getmore( sub { my ( $buffer, $length ) = @_; $body .= $buffer; return 1; } );
The bufsize parameter is as for get.
ACCESSORS
- code
-
Code of the request,
0
to6
inclusive. Pretty important, so is also returned by get.0
is an extension to the specification, and is used for connection errors (e.g. host not found) and other problems outside the gemini protocol. - content
-
The content, if any. Raw bytes. Only if the code is
2
. - error
-
The error message, if any.
- host
-
Host used for the request.
- meta
-
Gemini meta line. Use varies depending on the code.
- port
-
Port used for the request.
- socket
-
Socket to the server. May not be of much use after getmore is done with.
- status
-
Status of the request, a two digit number. Only set when the code is a gemini response (that is, not an internal
0
code). - uri
-
URI used for the request. Probably could be used with any relative URL returned from the server.
BUGS
None known. But it is a rather incomplete module; that may be considered a bug? The interface is very much subject to change.
SEE ALSO
gemini://gemini.circumlunar.space/docs/specification.gmi (v0.16.1)
COPYRIGHT AND LICENSE
Copyright 2022 Jeremy Mates
This program is distributed under the (Revised) BSD License: https://opensource.org/licenses/BSD-3-Clause