1
0
Fork 0
mirror of https://git.sr.ht/~adnano/go-gemini synced 2024-05-13 03:06:10 +02:00

Update documentation

This commit is contained in:
Adnan Maolood 2020-10-28 16:02:04 -04:00
parent 34ae2a9066
commit b5fbd197a1
4 changed files with 37 additions and 45 deletions

29
cert.go
View File

@ -8,7 +8,6 @@ import (
"crypto/x509"
"math/big"
"net"
"path"
"path/filepath"
"strings"
"time"
@ -36,9 +35,9 @@ func (c *CertificateStore) Add(scope string, cert tls.Certificate) {
c.store[scope] = cert
}
// Lookup returns the certificate for the given hostname.
func (c *CertificateStore) Lookup(hostname string) (*tls.Certificate, error) {
cert, ok := c.store[hostname]
// Lookup returns the certificate for the given scope.
func (c *CertificateStore) Lookup(scope string) (*tls.Certificate, error) {
cert, ok := c.store[scope]
if !ok {
return nil, ErrCertificateUnknown
}
@ -49,25 +48,9 @@ func (c *CertificateStore) Lookup(hostname string) (*tls.Certificate, error) {
return &cert, nil
}
// lookup returns the certificate for the given hostname + path.
func (c *CertificateStore) lookup(scope string) (*tls.Certificate, error) {
for {
cert, err := c.Lookup(scope)
switch err {
case ErrCertificateExpired, nil:
return cert, err
}
scope = path.Dir(scope)
if scope == "." {
break
}
}
return nil, ErrCertificateUnknown
}
// Load loads certificates from the given path.
// The path should lead to a directory containing certificates and private keys
// in the form hostname.crt and hostname.key.
// in the form scope.crt and scope.key.
// For example, the hostname "localhost" would have the corresponding files
// localhost.crt (certificate) and localhost.key (private key).
func (c *CertificateStore) Load(path string) error {
@ -81,8 +64,8 @@ func (c *CertificateStore) Load(path string) error {
if err != nil {
continue
}
hostname := strings.TrimSuffix(filepath.Base(crtPath), ".crt")
c.Add(hostname, cert)
scope := strings.TrimSuffix(filepath.Base(crtPath), ".crt")
c.Add(scope, cert)
}
return nil
}

View File

@ -6,6 +6,7 @@ import (
"crypto/x509"
"net"
"net/url"
"path"
"strings"
)
@ -153,12 +154,23 @@ func (c *Client) getClientCertificate(req *Request) (*tls.Certificate, error) {
if req.Certificate != nil {
return req.Certificate, nil
}
hostname, path := req.URL.Hostname(), strings.TrimSuffix(req.URL.Path, "/")
if cert, err := c.Certificates.lookup(hostname + path); err == nil {
// Remember the certificate used
req.Certificate = cert
return cert, nil
// Search recursively for the certificate
scope := req.URL.Hostname() + strings.TrimSuffix(req.URL.Path, "/")
for {
cert, err := c.Certificates.Lookup(scope)
if err == nil {
return cert, err
}
if err == ErrCertificateExpired {
break
}
scope = path.Dir(scope)
if scope == "." {
break
}
}
return &tls.Certificate{}, nil
}

22
doc.go
View File

@ -41,22 +41,12 @@ Clients can control when to trust certificates with TrustCertificate:
return knownHosts.Lookup(hostname, cert)
}
Clients can control what to do when a server requests a certificate:
Clients can create client certificates upon the request of a server:
client.GetCertificate = func(hostname string, store *gemini.CertificateStore) *tls.Certificate {
// If the certificate is in the store, return it
if cert, err := store.Lookup(hostname); err == nil {
return &cert
}
// Otherwise, generate a certificate
duration := time.Hour
cert, err := gemini.NewCertificate(hostname, duration)
if err != nil {
return nil
}
// Store and return the certificate
store.Add(hostname, cert)
return &cert
client.CreateCertificate = func(hostname, path string) *tls.Certificate {
return gemini.CreateCertificate(gemini.CertificateOptions{
Duration: time.Hour,
})
}
Server is a Gemini server.
@ -65,7 +55,7 @@ Server is a Gemini server.
Servers must be configured with certificates:
err := server.CertificateStore.Load("/var/lib/gemini/certs")
err := server.Certificates.Load("/var/lib/gemini/certs")
if err != nil {
// handle error
}

View File

@ -36,9 +36,16 @@ type responderKey struct {
}
// Register registers a responder for the given pattern.
// Patterns must be in the form of scheme://hostname (e.g. gemini://example.com).
//
// Patterns must be in the form of hostname or scheme://hostname
// (e.g. gemini://example.com).
// If no scheme is specified, a default scheme of gemini:// is assumed.
//
// Wildcard patterns are supported (e.g. *.example.com).
// To register a certificate for a wildcard domain, call Certificates.Add:
//
// var s gemini.Server
// s.Certificates.Add("*.example.com", cert)
func (s *Server) Register(pattern string, responder Responder) {
if pattern == "" {
panic("gemini: invalid pattern")