Class: Net::Gemini

Inherits:
Object
  • Object
show all
Includes:
Gemini::SSL
Defined in:
lib/net/gemini.rb

Overview

A Gemini client API for Ruby.

Net::Gemini provides a rich library which can be used to build Gemini user-agents. Net::Gemini is designed to work closely with URI.

Simple Examples

All examples assume you have loaded Net::Gemini with:

require 'net/gemini'

This will also require ‘uri’ so you don’t need to require it separately.

The Net::Gemini methods in the following section do not persist connections.

GET by URI

uri = URI('gemini://example.com/index.html?count=10')
Net::Gemini.get(uri) # => String

GET with Dynamic Parameters

uri = URI('gemini://example.com/index.html')
params = { :limit => 10, :page => 3 }
uri.query = URI.encode_www_form(params)

res = Net::Gemini.get_response(uri)
puts res.body if res.body_permitted?

Response Data

res = Net::Gemini.get_response(URI('gemini://exemple.com/home'))

# Status
puts res.status # => '20'
puts res.meta   # => 'text/gemini; charset=UTF-8; lang=en'

# Headers
puts res.header.inspect
# => { status: '20', meta: 'text/gemini; charset=UTF-8',
        mimetype: 'text/gemini', lang: 'en',
        charset: 'utf-8', format: nil }

The lang, charset and format headers will only be provided in case of ‘text/*` mimetype, and only if body for 2* status codes.

# Body
puts res.body if res.body_permitted?
puts res.body(flowed: 85)

Following Redirection

The #fetch method, contrary to the #request one will try to automatically resolves redirection, leading you to the final destination.

u = URI('gemini://exemple.com/redirect')
res = Net::Gemini.start(u.host, u.port) do |g|
  g.request(u)
end
puts "#{res.status} - #{res.meta}" # => '30 final/dest'
puts res.uri.to_s                  # => 'gemini://exemple.com/redirect'

u = URI('gemini://exemple.com/redirect')
res = Net::Gemini.start(u.host, u.port) do |g|
  g.fetch(u)
end
puts "#{res.status} - #{res.meta}" # => '20 - text/gemini;'
puts res.uri.to_s                  # => 'gemini://exemple.com/final/dest'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(host, port) ⇒ Gemini

Returns a new instance of Gemini.



95
96
97
98
99
# File 'lib/net/gemini.rb', line 95

def initialize(host, port)
  @host = host
  @port = port
  @certs_path = '~/.cache/gemini/certs'
end

Instance Attribute Details

#certs_path=(value) ⇒ Object (writeonly)

Sets the attribute certs_path

Parameters:

  • value

    the value to set the attribute certs_path to.



93
94
95
# File 'lib/net/gemini.rb', line 93

def certs_path=(value)
  @certs_path = value
end

Class Method Details

.get(uri) ⇒ Object



144
145
146
# File 'lib/net/gemini.rb', line 144

def get(uri)
  get_response(uri).body
end

.get_response(uri) ⇒ Object



140
141
142
# File 'lib/net/gemini.rb', line 140

def get_response(uri)
  start(uri.host, uri.port) { |gem| gem.fetch(uri) }
end

.start(host_or_uri, port = nil) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/net/gemini.rb', line 128

def start(host_or_uri, port = nil)
  if host_or_uri.is_a? URI::Gemini
    host = host_or_uri.host
    port = host_or_uri.port
  else
    host = host_or_uri
  end
  gem = new(host, port)
  return yield(gem) if block_given?
  gem
end

Instance Method Details

#fetch(uri, limit = 5) ⇒ Object

Raises:



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/net/gemini.rb', line 114

def fetch(uri, limit = 5)
  raise GeminiError, 'Too many Gemini redirects' if limit.zero?
  r = request(uri)
  return r unless r.status[0] == '3'
  begin
    uri = handle_redirect(r)
  rescue ArgumentError, URI::InvalidURIError
    return r
  end
  warn "Redirect to #{uri}" if $VERBOSE
  fetch(uri, limit - 1)
end

#request(uri) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/net/gemini.rb', line 101

def request(uri)
  init_sockets
  req = GeminiRequest.new uri
  req.write @ssl_socket
  res = GeminiResponse.read_new(@ssl_socket)
  res.uri = uri
  res.reading_body(@ssl_socket)
ensure
  # Stop remaining connection, even if they should be already cut
  # by the server
  finish
end