9 Commits
v0.2.2 ... main

Author SHA1 Message Date
4985bf0bc8 Add link to ogirinal in readme 2023-05-26 00:45:08 -04:00
f6d3c47816 Export TLS & remove conn in request struct
This makes it possible to fully create another request outside of this module
(which Hnakra will need) and has better parity with net/http.
2023-05-26 00:38:12 -04:00
24d70951c9 Change package URL in go.mod 2023-05-26 00:37:56 -04:00
b436ec8cb5 Change import paths 2023-05-25 18:45:53 -04:00
54f7209f13 Update readme 2023-05-25 18:27:52 -04:00
Adnan Maolood
b0f27c6f74 fs: Prevent invalid directory links
A file with a name like "gemini:example" would previously result in the
following invalid link:

    => gemini:example gemini:example

Fix by prepending a "./" before each filename, so that the resulting
link looks like:

    => ./gemini:example gemini:example
2022-05-07 13:54:56 -04:00
Yujiri
8c0af18617 Fix parsing of list item lines
According to section 5.5.2 of the Gemini specification (v0.16.1), the
space is mandatory.
2022-03-15 11:07:04 -04:00
Adnan Maolood
353416685a doc: Fix Mux documentation 2022-02-16 12:01:55 -05:00
Adnan Maolood
0ceec22705 readme: Update Gemini specification version 2021-12-18 12:51:04 -05:00
13 changed files with 30 additions and 52 deletions

View File

@@ -1,16 +1,18 @@
# go-gemini
[![godocs.io](https://godocs.io/git.sr.ht/~adnano/go-gemini?status.svg)](https://godocs.io/git.sr.ht/~adnano/go-gemini) [![builds.sr.ht status](https://builds.sr.ht/~adnano/go-gemini.svg)](https://builds.sr.ht/~adnano/go-gemini?)
This repository is a fork of [go-gemini](https://godocs.io/git.sr.ht/~adnano/go-gemini)
implementing better parity with net/http and some tweaks required for use in
[Hnakra](https://git.tebibyte.media/sashakoshka/hnakra).
Package gemini implements the [Gemini protocol](https://gemini.circumlunar.space)
in Go. It provides an API similar to that of net/http to facilitate the
development of Gemini clients and servers.
Compatible with version v0.14.3 of the Gemini specification.
Compatible with version v0.16.0 of the Gemini specification.
## Usage
import "git.sr.ht/~adnano/go-gemini"
import "git.tebibyte.media/sashakoshka/go-gemini"
Note that some filesystem-related functionality is only available on Go 1.16
or later as it relies on the io/fs package.
@@ -22,12 +24,6 @@ To run an example:
go run examples/server.go
## Contributing
Send patches and questions to [~adnano/go-gemini-devel](https://lists.sr.ht/~adnano/go-gemini-devel).
Subscribe to release announcements on [~adnano/go-gemini-announce](https://lists.sr.ht/~adnano/go-gemini-announce).
## License
go-gemini is licensed under the terms of the MIT license (see LICENSE).

6
doc.go
View File

@@ -30,7 +30,7 @@ Servers should be configured with certificates:
server.GetCertificate = certificates.Get
Mux is a Gemini request multiplexer.
Mux can handle requests for multiple hosts and schemes.
Mux can handle requests for multiple hosts and paths.
mux := &gemini.Mux{}
mux.HandleFunc("example.com", func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
@@ -39,8 +39,8 @@ Mux can handle requests for multiple hosts and schemes.
mux.HandleFunc("example.org/about.gmi", func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
fmt.Fprint(w, "About example.org")
})
mux.HandleFunc("http://example.net", func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
fmt.Fprint(w, "Proxied content from http://example.net")
mux.HandleFunc("/images/", func(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
w.WriteHeader(gemini.StatusGone, "Gone forever")
})
server.Handler = mux

View File

@@ -10,8 +10,8 @@ import (
"log"
"time"
"git.sr.ht/~adnano/go-gemini"
"git.sr.ht/~adnano/go-gemini/certificate"
"git.tebibyte.media/sashakoshka/go-gemini"
"git.tebibyte.media/sashakoshka/go-gemini/certificate"
)
type User struct {
@@ -52,7 +52,7 @@ func fingerprint(cert *x509.Certificate) string {
}
func profile(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
tls := r.TLS()
tls := r.TLS
if len(tls.PeerCertificates) == 0 {
w.WriteHeader(gemini.StatusCertificateRequired, "Certificate required")
return
@@ -68,7 +68,7 @@ func profile(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
}
func changeUsername(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
tls := r.TLS()
tls := r.TLS
if len(tls.PeerCertificates) == 0 {
w.WriteHeader(gemini.StatusCertificateRequired, "Certificate required")
return

View File

@@ -11,7 +11,7 @@ import (
"os"
"time"
"git.sr.ht/~adnano/go-gemini/certificate"
"git.tebibyte.media/sashakoshka/go-gemini/certificate"
)
func main() {

View File

@@ -16,8 +16,8 @@ import (
"os"
"path/filepath"
"git.sr.ht/~adnano/go-gemini"
"git.sr.ht/~adnano/go-gemini/tofu"
"git.tebibyte.media/sashakoshka/go-gemini"
"git.tebibyte.media/sashakoshka/go-gemini/tofu"
)
var (

View File

@@ -10,7 +10,7 @@ import (
"io"
"os"
"git.sr.ht/~adnano/go-gemini"
"git.tebibyte.media/sashakoshka/go-gemini"
)
func main() {

View File

@@ -11,8 +11,8 @@ import (
"os/signal"
"time"
"git.sr.ht/~adnano/go-gemini"
"git.sr.ht/~adnano/go-gemini/certificate"
"git.tebibyte.media/sashakoshka/go-gemini"
"git.tebibyte.media/sashakoshka/go-gemini/certificate"
)
func main() {

View File

@@ -10,8 +10,8 @@ import (
"log"
"time"
"git.sr.ht/~adnano/go-gemini"
"git.sr.ht/~adnano/go-gemini/certificate"
"git.tebibyte.media/sashakoshka/go-gemini"
"git.tebibyte.media/sashakoshka/go-gemini/certificate"
)
func main() {

2
fs.go
View File

@@ -169,7 +169,7 @@ func dirList(w ResponseWriter, f fs.File) {
}
link := LineLink{
Name: name,
URL: (&url.URL{Path: name}).EscapedPath(),
URL: "./" + url.PathEscape(name),
}
fmt.Fprintln(w, link.String())
}

2
go.mod
View File

@@ -1,4 +1,4 @@
module git.sr.ht/~adnano/go-gemini
module git.tebibyte.media/sashakoshka/go-gemini
go 1.15

View File

@@ -4,7 +4,6 @@ import (
"bufio"
"crypto/tls"
"io"
"net"
"net/url"
)
@@ -28,8 +27,7 @@ type Request struct {
// This field is ignored by the Gemini server.
Certificate *tls.Certificate
conn net.Conn
tls *tls.ConnectionState
TLS *tls.ConnectionState
}
// NewRequest returns a new request.
@@ -98,30 +96,11 @@ func (r *Request) WriteTo(w io.Writer) (int64, error) {
return wrote, bw.Flush()
}
// Conn returns the network connection on which the request was received.
// Conn returns nil for client requests.
func (r *Request) Conn() net.Conn {
return r.conn
}
// TLS returns information about the TLS connection on which the
// request was received.
// TLS returns nil for client requests.
func (r *Request) TLS() *tls.ConnectionState {
if r.tls == nil {
if tlsConn, ok := r.conn.(*tls.Conn); ok {
state := tlsConn.ConnectionState()
r.tls = &state
}
}
return r.tls
}
// ServerName returns the value of the TLS Server Name Indication extension
// sent by the client.
// ServerName returns an empty string for client requests.
func (r *Request) ServerName() string {
if tls := r.TLS(); tls != nil {
if tls := r.TLS; tls != nil {
return tls.ServerName
}
return ""

View File

@@ -371,7 +371,10 @@ func (srv *Server) goServeConn(ctx context.Context, conn net.Conn) error {
w.WriteHeader(StatusBadRequest, "Bad request")
return w.Flush()
}
req.conn = conn
if tlsConn, ok := conn.(*tls.Conn); ok {
state := tlsConn.ConnectionState()
req.TLS = &state
}
h := srv.Handler
if h == nil {

View File

@@ -125,8 +125,8 @@ func ParseLines(r io.Reader, handler func(Line)) error {
name = strings.TrimLeft(name, spacetab)
line = LineLink{url, name}
}
} else if strings.HasPrefix(text, "*") {
text = text[1:]
} else if strings.HasPrefix(text, "* ") {
text = text[2:]
text = strings.TrimLeft(text, spacetab)
line = LineListItem(text)
} else if strings.HasPrefix(text, "###") {