Update documentation
This commit is contained in:
parent
34ae2a9066
commit
b5fbd197a1
29
cert.go
29
cert.go
@ -8,7 +8,6 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -36,9 +35,9 @@ func (c *CertificateStore) Add(scope string, cert tls.Certificate) {
|
|||||||
c.store[scope] = cert
|
c.store[scope] = cert
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup returns the certificate for the given hostname.
|
// Lookup returns the certificate for the given scope.
|
||||||
func (c *CertificateStore) Lookup(hostname string) (*tls.Certificate, error) {
|
func (c *CertificateStore) Lookup(scope string) (*tls.Certificate, error) {
|
||||||
cert, ok := c.store[hostname]
|
cert, ok := c.store[scope]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrCertificateUnknown
|
return nil, ErrCertificateUnknown
|
||||||
}
|
}
|
||||||
@ -49,25 +48,9 @@ func (c *CertificateStore) Lookup(hostname string) (*tls.Certificate, error) {
|
|||||||
return &cert, nil
|
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.
|
// Load loads certificates from the given path.
|
||||||
// The path should lead to a directory containing certificates and private keys
|
// 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
|
// For example, the hostname "localhost" would have the corresponding files
|
||||||
// localhost.crt (certificate) and localhost.key (private key).
|
// localhost.crt (certificate) and localhost.key (private key).
|
||||||
func (c *CertificateStore) Load(path string) error {
|
func (c *CertificateStore) Load(path string) error {
|
||||||
@ -81,8 +64,8 @@ func (c *CertificateStore) Load(path string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
hostname := strings.TrimSuffix(filepath.Base(crtPath), ".crt")
|
scope := strings.TrimSuffix(filepath.Base(crtPath), ".crt")
|
||||||
c.Add(hostname, cert)
|
c.Add(scope, cert)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
22
client.go
22
client.go
@ -6,6 +6,7 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -153,12 +154,23 @@ func (c *Client) getClientCertificate(req *Request) (*tls.Certificate, error) {
|
|||||||
if req.Certificate != nil {
|
if req.Certificate != nil {
|
||||||
return 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 {
|
// Search recursively for the certificate
|
||||||
// Remember the certificate used
|
scope := req.URL.Hostname() + strings.TrimSuffix(req.URL.Path, "/")
|
||||||
req.Certificate = cert
|
for {
|
||||||
return cert, nil
|
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
|
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)
|
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 {
|
client.CreateCertificate = func(hostname, path string) *tls.Certificate {
|
||||||
// If the certificate is in the store, return it
|
return gemini.CreateCertificate(gemini.CertificateOptions{
|
||||||
if cert, err := store.Lookup(hostname); err == nil {
|
Duration: time.Hour,
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Server is a Gemini server.
|
Server is a Gemini server.
|
||||||
@ -65,7 +55,7 @@ Server is a Gemini server.
|
|||||||
|
|
||||||
Servers must be configured with certificates:
|
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 {
|
if err != nil {
|
||||||
// handle error
|
// handle error
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,16 @@ type responderKey struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register registers a responder for the given pattern.
|
// 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.
|
// If no scheme is specified, a default scheme of gemini:// is assumed.
|
||||||
|
//
|
||||||
// Wildcard patterns are supported (e.g. *.example.com).
|
// 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) {
|
func (s *Server) Register(pattern string, responder Responder) {
|
||||||
if pattern == "" {
|
if pattern == "" {
|
||||||
panic("gemini: invalid pattern")
|
panic("gemini: invalid pattern")
|
||||||
|
Loading…
Reference in New Issue
Block a user