Update documentation
This commit is contained in:
parent
34ae2a9066
commit
b5fbd197a1
29
cert.go
29
cert.go
@ -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
|
||||
}
|
||||
|
22
client.go
22
client.go
@ -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
22
doc.go
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user