Net::Gemini(3pm)
π NAME π
This is the Net::Gemini(3pm) page from User Contributed Perl Documentation, bestie, and it's all about Net::Gemini β a small gemini client. π¦β¨
β¨ SYNOPSIS β¨
okay so the vibe check starts like this:
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 collect on the socket ... }
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 πΈ
okay so this module implements code that may help implement a gemini protocol client in Perl β that's the whole assignment, no cap. π
π¨ CAVEATS π¨
It's a pretty beta module. lowkey important.
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>
π« FUNCTION π«
gemini_request URI [ options ... ]
A utility function that is not exported by default; it calls the get method and handles redirects and the collection of content, if any.
use Net::Gemini 'gemini_request';
my ( $gem, $code ) = gemini_request( 'gemini://...', ... );
A code 2 will result in the mime accessor being populated with the Content-Type by way of the parse_mime_type function from Parse::MIME.
A notable difference here is that a code of 3 indicates that too many redirects were encountered, not that there was a redirect. This should be considered an error. π©
The socket will be closed when this call ends.
Options include:
bufsize => strictly-positive-integerβ Buffer size to use for reads from the socket.4096by default.content_callback => code-referenceβ Custom callback to handle one or more portions of the request content with, same as thegetmoreinterface. If a callback is not provided the content will be collected into the object via thecontentaccessor. The callback is given the current buffer (raw), the length of that buffer, and a reference to the gemini object.
gemini_request( $uri, content_callback => sub {
my ( $buffer, $length, $gem ) = @_;
...
return 1;
});
Processing will stop if the callback returns a false value.
max_size => strictly-positive-integerβ Maximum content size to collect intocontent. Ignored if a custom callback is provided. The code will be zero and the error will be"max_size"and the status will start with2and the content will be truncated if the response is larger than permitted.max_redirects => strictly-positive-integerβ How many redirections should be followed.5is the default.redirect_delay => floating-pointβ How long to delay between redirects, by default1second. There is a delay by default because gemini servers or firewalls may rate limit requests, or the gemini server simply may not have much CPU available.param => hash-referenceβ Parameters that will be passed to thegetmethod.
π οΈ 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 be 0 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 of 1 to 6 inclusive, which will indicate the next steps any subsequent code should take.
For code 2 responses the response body may be split between _buf and whatever remains unread in the socket, if anything, hence the getmore method or the gemini_request utility function.
Parameters include:
bufsize => strictly-positive-integerβ Size of buffer to use for requests,4096by default. Note that a naughty server may return data in far smaller increments than this.ssl => { params }β Passes the given parameters to theIO::Socket::SSLconstructor. 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 via"SSL_hostname"."Timeout"can be used to set a connect timeout on the socket. However, a server could wedge at any point following, so it may be necessary to wrap agetrequest with the"alarm"function or similar.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 possibly"SSL_verifycn_name"via thesslparam 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 is passed a hash reference containing various information about the certificate and connection.
...->get( $url, ..., verify_ssl => sub {
my ($param) = @_;
return 1 if int rand 2; # certificate is OK
return 0;
} );
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.
See bin/gmitool for how verify_ssl might be used in a client.
In module version 0.08 the format of the digest (fingerprint) changed to be compatible with the amfora gemini client.
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 π
Or you can use the faster hash internals, which are not expected to change.
codeβ Code of the request,0to6inclusive. Pretty important, so is also returned byget.0is 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 is2and a suitablegemini_requestcall has been made.errorβ The error message, if any.hostβ Host used for the request.ipβ IP address used for the request.metaβ Gemini meta line. Use varies depending on the code.mimeβ Only set bygemini_requestfor2code responses; contains an array reference of return values from theparse_mime_typefunction ofParse::MIME.portβ Port used for the request.socketβ Socket to the server. May not be of much use aftergetmoreis done with, or aftergemini_request.statusβ Status of the request, a two digit number. Only set when the code is a gemini response (that is, not an internal0code).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 somewhat incomplete module, and the specification may change, too. Not me being dramatic β that's literally what it says. π
π SEE ALSO π
<gemini://gemini.circumlunar.space/docs/specification.gmi>(v0.16.1)<gemini://gemini.thebackupbox.net/test/torture>RFC 2045
π COPYRIGHT AND LICENSE π
Copyright 2022 Jeremy Mates
This program is distributed under the (Revised) BSD License:
<https://opensource.org/licenses/BSD-3-Clause>
okay bestie, that's the page!! π The footer energy is source/version perl v5.42.2, dated 2026-02-15, and the manual name is Net::Gemini(3pm). mwah πβ¨
π¦ where this page comes from
- alpine 3.24: perl-net-gemini-doc 0.11-r1 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms