Documentation
¶
Index ¶
- Constants
- func ErrorResponse(statuscode int, meta string) error
- func GenerateClientCertificate() (*tls.Certificate, error)
- func ListenAndServe(addr string, handler Handler) error
- func Serve(listener net.Listener, handler Handler) error
- func ServeBadRequest(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeCGIError(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeGone(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeInput(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeNotFound(ctx context.Context, w ResponseWriter, a ...any) error
- func ServePermanentFailure(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeProxyError(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeProxyRequestRefused(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeRedirectPermanent(ctx context.Context, w ResponseWriter, target string) error
- func ServeRedirectTemporary(ctx context.Context, w ResponseWriter, target string) error
- func ServeSensitiveInput(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeServerUnavailable(ctx context.Context, w ResponseWriter, a ...any) error
- func ServeSlowDown(ctx context.Context, w ResponseWriter, numberOfSecondsToWait uint) error
- func ServeTemporaryFailure(ctx context.Context, w ResponseWriter, a ...any) error
- func StatusText(code int) string
- type Field
- type FileSystemHandler
- type Handler
- type HandlerFunc
- type Logger
- type Request
- func (receiver Request) IsNothing() bool
- func (receiver Request) MarshalText() ([]byte, error)
- func (receiver *Request) Parse(src any) error
- func (receiver Request) RequestValue() string
- func (receiver Request) Scheme() string
- func (receiver Request) String() string
- func (receiver Request) TCPAddr() (string, bool)
- func (receiver *Request) UnmarshalText(text []byte) error
- func (receiver Request) WriteTo(w io.Writer) (int64, error)
- type ResponseBadRequest
- type ResponseCGIError
- type ResponseCertificateNotAuthorized
- type ResponseCertificateNotValid
- type ResponseCertificateRequired
- type ResponseGone
- type ResponseInput
- type ResponseNotFound
- type ResponsePermanentFailure
- type ResponseProxyError
- type ResponseProxyRequestRefused
- type ResponseReader
- func Call(ctx context.Context, conn net.Conn, request Request) (ResponseReader, error)
- func DialAndCall(ctx context.Context, addr string, request Request) (ResponseReader, error)
- func DialAndCallTLS(ctx context.Context, addr string, request Request, tlsHandler TLSHandler) (ResponseReader, error)
- func DialAndCallURL(ctx context.Context, url string, tlsHandler TLSHandler) (ResponseReader, error)
- type ResponseRedirectPermanent
- type ResponseRedirectTemporary
- type ResponseSensitiveInput
- type ResponseServerUnavailable
- type ResponseSlowDown
- type ResponseTemporaryFailure
- type ResponseWriter
- type Server
- type TLSConfig
- type TLSHandler
- type TimeoutHandler
- type UnknownResponse
- type UserDirHandler
Constants ¶
const ( DefaultMetaInput = StatusTextInput // 10 DefaultMetaSensitiveInput = StatusTextSensitiveInput // 11 DefaultMetaSuccess = StatusTextSuccess // 20 DefaultMetaTemporaryFailure = StatusTextTemporaryFailure // 40 DefaultMetaCGIError = StatusTextCGIError // 42 DefaultMetaProxyError = StatusTextProxyError // 43 DefaultMetaSlowDown = "3" // 44 DefaultMetaPermanentFailure = StatusTextPermanentFailure // 50 DefaultMetaNotFound = StatusTextNotFound // 51 DefaultMetaGone = StatusTextGone // 52 DefaultMetaProxyRequestRefused = StatusTextProxyRequestRefused // 53 DefaultMetaBadRequest = StatusTextBadRequest // 59 )
These are constants that can be used as default values for a Mercury Protocol's response‐header's meta.
For example usage:
hg.ServeNotFound(ctx, w, hg.DefaultMetaNotFound)
Also for another example usage:
hg.ServeTemporaryFailure(ctx, w, hg.DefaultMetaTemporaryFailure)
To understand these —
The Mercury Protocol is based on Gemini Protocol. And therefore a Mercury Protocol response‐header's structure is defined in the Gemini Protocol's specification. In the Gemini Protocol specification, the response‐header is described as follows:
<STATUS><SPACE><META><CR><LF>
In Go code, this (the Mercury Protocol's response‐header) is equivalent to:
twoDigitStatusNumericalCode + " " + meta + "\r\n"
For most Mercury Protocol response types, the value of the response‐header's ‘meta’ is likely cosmetic. And possibly, no human will ever see them (depending on whether the client software presents them to the user or not). The following constants provide useful default values for these cosmetic meta value's, that can make a programmer's life easier when developing a Mercury Protocol client or server:
- DefaultMetaSuccess = "success" // 20
- DefaultMetaTemporaryFailure = "temporary-failure" // 40
- DefaultMetaServerUnavailable = "server-unavailable" // 41
- DefaultMetaCGIError = "cgi-error" // 42
- DefaultMetaProxyError = "proxy-error" // 43
- DefaultMetaPermanentFailure = "permanent-failure" // 50
- DefaultMetaNotFound = "not-found" // 51
- DefaultMetaGone = "gone" // 52
- DefaultMetaProxyRequestRefused = "proxy-request-refused" // 53
- DefaultMetaBadRequest = "bad-request" // 59
Two of these default response‐header’s ‘meta’ are (not cosmetic but are) shown to the user. The programmer SHOULD create their own message; but just in case they don't, these default values exist:
• DefaultMetaInput = "input" // 10
• DefaultMetaSensitiveInput = "sensitive-input" // 11
In addition to these, one of these default response‐header is functional.
DefaultMetaSlowDown = "3" // 44
For status 44, the meta is the number of seconds the client MUST wait before making another request. So "3" means "wait 3 seconds before retrying". This SHOULD be chosen by the programmer; but just in case they don't, a default value exists.
const ( // A Mercury Protocol server runs over TCP. // TCP has communications happening over TCP-ports. // A client-server protocol (including the Mercury Protocol) typically defines a default-TCP-port for servers. // For the Mercury Protocol, this default-TCP-port is: 1961. // // This constant — ‘DefaultTCPPort’ — can be used when one wants to use the default-TCP-port for a Mercury Protocol server. // // For example: // // var domain string = "example.com" // // var address string = fmt.Sprintf("%s:%d", domain, hg.DefaultTCPPort) // // err := hg.ListenAndServe(address, handler) DefaultTCPPort = 1961 DefaultTCPPortString = "1961" // A Gemini Protocol server runs over TLS over TCP. // TCP has communications happening over TCP-ports. // A client-server protocol (including the Gemini Protocol) typically defines a default-TCP-port for servers. // For the Gemini Protocol, this default-TCP-port is: 1965. // // This constant — ‘DefaultTCPPortTLS’ — can be used when one wants to use the default-TCP-port for a Gemini Protocol server. // // For example: // // var domain string = "example.com" // // var address string = fmt.Sprintf("%s:%d", domain, hg.DefaultTCPPortTLS) // // err := hg.ListenAndServe(address, handler) DefaultTCPPortTLS = 1965 DefaultTCPPortTLSString = "1965" )
const ( ErrBadStatusCode = erorr.Error("bad status code") ErrBadResponseHeaderMeta = erorr.Error("bad response header meta") ErrBadTCPAddr = erorr.Error("bad TCP address") ErrCannotParse = erorr.Error("cannot parse") ErrContextDone = erorr.Error("context done") ErrDialError = erorr.Error("dial error") ErrNilNetworkConnection = erorr.Error("nil network connection") ErrNilReceiver = erorr.Error("nil receiver") ErrNilResponseReader = erorr.Error("nil response reader") ErrNilResponseWriter = erorr.Error("nil response writer") ErrRequestIsNothing = erorr.Error("request is nothing") ErrResponseHeaderMetaTooBig = erorr.Error("response header meta too big") ErrSchemeUnsupported = erorr.Error("scheme unsupported") ErrServerCertificateNotFound = erorr.Error("server did not present any certificate(s)") ErrServerShutdown = erorr.Error("server shutdown") ErrTargetTypeUnsupported = erorr.Error("target type unsupported") ErrWriteError = erorr.Error("write error") )
const ( Scheme = "mercury" SchemeTLS = "gemini" )
const ( StatusInput = 10 StatusSensitiveInput = 11 StatusSuccess = 20 StatusRedirectTemporary = 30 StatusRedirectPermanent = 31 StatusTemporaryFailure = 40 StatusCGIError = 42 StatusProxyError = 43 StatusSlowDown = 44 StatusPermanentFailure = 50 StatusNotFound = 51 StatusGone = 52 StatusProxyRequestRefused = 53 StatusBadRequest = 59 // Gemini Protocol only. // Not used in the Mercury Protocol. StatusCertificateRequired = 60 StatusCertificateNotAuthorized = 61 StatusCertificateNotValid = 62 )
Constants for the Mercury Protocol status codes.
Can use, for example, with ResponseWriter's WriteHeader method.
For example:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
w.WriteHeader(ctx, hg.StatusNotFound, "uh oh!")
}
const ( StatusTextInput = "input" // 10 StatusTextSensitiveInput = "sensitive-input" // 11 StatusTextSuccess = "success" // 20 StatusTextRedirectTemporary = "temporary-redirection" // 30 StatusTextRedirectPermanent = "permanent-redirection" // 31 StatusTextTemporaryFailure = "temporary-failure" // 40 StatusTextCGIError = "cgi-error" // 42 StatusTextProxyError = "proxy-error" // 43 StatusTextSlowDown = "slow-down" // 44 StatusTextPermanentFailure = "permanent-failure" // 50 StatusTextNotFound = "not-found" // 51 StatusTextGone = "gone" // 52 StatusTextProxyRequestRefused = "proxy-request-refused" // 53 StatusTextBadRequest = "bad-request" // 59 // Gemini Protocol only. // Not used in the Mercury Protocol. StatusTextCertificateRequired = "certificate-required" // 60 StatusTextCertificateNotAuthorized = "certificate-not-authorized" // 61 StatusTextCertificateNotValid = "certificate-not-valid" // 62 )
const DebugHandler internalDebugHandler = internalDebugHandler(0)
The DebugHandler can be used as:
- a demo Mercury Protocol server,
- a debugging tool to use with Mercury Protocol clients.
You can use it with code similar to:
const address = ":1961" err := hg.ListenAndServe(address, hg.DebugHandler)
Variables ¶
This section is empty.
Functions ¶
func ErrorResponse ¶
ErrorResponse returns the appropriate response type for the given status-code & meta.
And note that any Mercury Protocol response type other that “20 SUCCESS” is considered an error.
Example With Bad Request ¶
So, for example, this:
hg.ErrorResponse(59, "")
Would return:
hg.ResponseBadRequest{meta:""}
Example With Temporary Failure ¶
And, for example, this:
hg.ErrorResponse(40, "we seem to be experiencing some technical difficulties")
Would return:
hg.ResponseTemporaryFailure{meta:"we seem to be experiencing some technical difficulties"}
Example With Success ¶
Although note that calling with a status-code of 20 (i.e., the status code for Success) would return nil. So, for example, this:
hg.ErrorResponse(20, "text/gemini")
Would return
nil
Type Switch ¶
This is useful with type switches. For example:
func callMercury(rr hg.ResponseReader, r hg.Request) {
// ...
p, err := io.ReadAll(rr.Reader(ctx))
if nil != err {
switch casted := err.(type) {
case hg.ResponseInput:
//@TODO
case hg.ResponseSensitiveInput:
//@TODO
case hg.ResponseRedirectTemporary:
//@TODO
case hg.ResponseRedirectPermanent:
//@TODO
case hg.ResponseTemporaryFailure:
//@TODO
case hg.ResponseServerUnavailable:
//@TODO
case hg.ResponseCGIError:
//@TODO
case hg.ResponseProxyError:
//@TODO
case hg.ResponseSlowDown:
//@TODO
case hg.ResponsePermanentFailure:
//@TODO
case hg.ResponseNotFound :
//@TODO
case hg.ResponseGone:
//@TODO
case hg.ResponseProxyRequestRefused:
//@TODO
case hg.ResponseBadRequest:
//@TODO
case hg.ResponseCertificateRequired:
//@TODO
case hg.ResponseCertificateNotAuthorized:
//@TODO
case hg.ResponseCertificateNotValid:
//@TODO
case hg.UnknownResponse:
//@TODO
default:
//@TODO
}
// ...
}
func GenerateClientCertificate ¶
func GenerateClientCertificate() (*tls.Certificate, error)
GenerateClientCertificate generates a self-signed TLS client certificate and returns it directly as a *tls.Certificate (including private-key).
This is useful when speaking protocols that use TLS client certificates for identity (such as the Gemini Protocol). In the Gemini Protocol, a server may respond with a "60 CLIENT CERTIFICATE REQUIRED" status code, indicating the client must present a certificate. Gemini clients routinely generate throwaway or per-site self-signed certificates on the fly when this happens.
Example usage:
rr, err := hg.DialAndCallTLS(ctx, addr, request, nil)
// ... get back ResponseCertificateRequired ...
cert, err := hg.GenerateClientCertificate()
rr, err = hg.DialAndCallTLS(ctx, addr, request, hg.TLSConfig{
ClientCertificateFunc: func(host string) *tls.Certificate {
return cert
},
})
See also:
func ListenAndServe ¶
ListenAndServe listens on the TCP network address `addr` and then spawns a call to the ServeMercury method on the `handler` to serve each incoming connection.
For a very simple example:
package main
import (
"github.com/reiver/go-hg"
)
func main() {
//@TODO: In your code, you would probably want to use a different handler.
var handler hg.Handler = hg.DebugHandler
err := hg.ListenAndServe(":1961", handler)
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
}
func Serve ¶
Serve accepts an incoming Mercury Protocol client connection on the net.Listener `listener`.
For a very simple example:
package main
import (
"github.com/reiver/go-hg"
"net"
)
func main() {
listener, err := net.Listen("tcp", ":1961")
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
//@TODO: In your code, you would probably want to use a different handler.
var handler hg.Handler = hg.DebugHandler
err = hg.Serve(listener, handler)
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
}
func ServeBadRequest ¶
func ServeBadRequest(ctx context.Context, w ResponseWriter, a ...any) error
59 BAD REQUEST
This function sends a “59 BAD REQUEST” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "you did not enter a number"
hg.ServeBadRequest(ctx, w, message)
// ...
}
func ServeCGIError ¶
func ServeCGIError(ctx context.Context, w ResponseWriter, a ...any) error
42 CGI ERROR
This function sends a “42 CGI ERROR” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "the program being run just had an unexpected fatal error"
hg.ServeCGIError(ctx, w, message)
// ...
}
func ServeGone ¶
func ServeGone(ctx context.Context, w ResponseWriter, a ...any) error
52 GONE
This function sends a “52 GONE” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "he's dead jim"
hg.ServeGone(ctx, w, message)
// ...
}
func ServeInput ¶
func ServeInput(ctx context.Context, w ResponseWriter, a ...any) error
10 INPUT
This function sends a “10 INPUT” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var prompt string = "Pick a number between 1 and 10"
hg.ServeInput(ctx, w, prompt)
// ...
}
func ServeNotFound ¶
func ServeNotFound(ctx context.Context, w ResponseWriter, a ...any) error
51 NOT FOUND
This function sends a “51 NOT FOUND” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "this is not the gem-page you are looking for"
hg.ServeNotFound(ctx, w, message)
// ...
}
func ServePermanentFailure ¶
func ServePermanentFailure(ctx context.Context, w ResponseWriter, a ...any) error
50 PERMANENT FAILURE
This function sends a “50 PERMANENT FAILURE” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "someone deleted the database"
hg.ServePermanentFailure(ctx, w, message)
// ...
}
func ServeProxyError ¶
func ServeProxyError(ctx context.Context, w ResponseWriter, a ...any) error
43 PROXY ERROR
This function sends a “43 PROXY ERROR” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "the proxy server providing TLS encryption errored out"
hg.ServeProxyError(ctx, w, message)
// ...
}
func ServeProxyRequestRefused ¶
func ServeProxyRequestRefused(ctx context.Context, w ResponseWriter, a ...any) error
53 PROXY REQUEST REFUSED
This function sends a “53 PROXY REQUEST REFUSED” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "you did not enter a number"
hg.ServeProxyRequestRefused(ctx, w, message)
// ...
}
func ServeRedirectPermanent ¶
func ServeRedirectPermanent(ctx context.Context, w ResponseWriter, target string) error
31 REDIRECT - PERMANENT
This function sends a “31 REDIRECT - PERMANENT” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
//var url string = "/apple/banana/cherry.txt"
//var url string = "documents/info.txt"
var url string = "mercury://example.com/once/twice/thrice/fource.txt"
hg.ServeRedirectPermanent(ctx, w, url)
// ...
}
func ServeRedirectTemporary ¶
func ServeRedirectTemporary(ctx context.Context, w ResponseWriter, target string) error
30 REDIRECT - TEMPORARY
This function sends a “30 REDIRECT - TEMPORARY” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
//var url string = "/apple/banana/cherry.txt"
//var url string = "documents/info.txt"
var url string = "mercury://example.com/once/twice/thrice/fource.txt"
hg.ServeRedirectTemporary(ctx, w, url)
// ...
}
func ServeSensitiveInput ¶
func ServeSensitiveInput(ctx context.Context, w ResponseWriter, a ...any) error
11 SENSITIVE INPUT
This function sends a “11 SENSITIVE INPUT” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var prompt string = "Please enter your password"
hg.ServeSensitiveInput(ctx, w, prompt)
// ...
}
func ServeServerUnavailable ¶
func ServeServerUnavailable(ctx context.Context, w ResponseWriter, a ...any) error
41 SERVER UNAVAILABLE
This function sends a “41 SERVER UNAVAILABLE” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "we are upgrading the server"
hg.ServeServerUnavailable(ctx, w, message)
// ...
}
func ServeSlowDown ¶
func ServeSlowDown(ctx context.Context, w ResponseWriter, numberOfSecondsToWait uint) error
44 SLOW DOWN
This function sends a “44 SLOW DOWN” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var numberOfSecondsToWait uint = 8
hg.ServeSlowDown(ctx, w, numberOfSecondsToWait)
// ...
}
func ServeTemporaryFailure ¶
func ServeTemporaryFailure(ctx context.Context, w ResponseWriter, a ...any) error
40 TEMPORARY FAILURE
This function sends a “40 TEMPORARY FAILURE” Mercury Protocol response.
Example Usage ¶
This is how one might use this helper-function:
func ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
var message string = "try again later"
hg.ServeTemporaryFailure(ctx, w, message)
// ...
}
func StatusText ¶
Types ¶
type Field ¶
type Field = field.StringlyField
type FileSystemHandler ¶
FileSystemHandler is used to create a Mercury Protocol server that serves files from a fs.FS file system.
For example usage:
var fshandler hg.FileSystemHandler
fshandler.Root = os.DirFS("/path/to/mercury/root")
var handler hg.Handler = &fshandler
err := hg.ListenAndServe(":1961", handler)
func (FileSystemHandler) ServeMercury ¶
func (receiver FileSystemHandler) ServeMercury(ctx context.Context, w ResponseWriter, r Request)
type Handler ¶
type Handler interface {
ServeMercury(ctx context.Context, w ResponseWriter, r Request)
}
Handler represents something that responds to a Mercury Protocol request.
Typically, someone who wants to create a custom Mercury Protocol server would create a type that fits this Handler interface, and then (directly or indirectly) pass it to the Serve or ListenAndServe functions.
type HandlerFunc ¶
type HandlerFunc func(context.Context, ResponseWriter, Request)
HandlerFunc is an adapter that allows one to turn a function into a Handler if the function has the same signature as ServeMercury.
For example:
func doIt(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
}
// ...
var handler hg.Handler = hg.HandlerFunc(doIt)
func (HandlerFunc) ServeMercury ¶
func (fn HandlerFunc) ServeMercury(ctx context.Context, w ResponseWriter, r Request)
type Request ¶
type Request struct {
// contains filtered or unexported fields
}
Request represents a Mercury Protocol request — either received by a server, or being sent by a client.
A client may create a Mercury Protocol request with code similar to the following:
var request hg.Request
err := request.Parse("mercury://example.com/apple/banana/cherry.txt")
A server would receive the request as a parameter to the ServeMercury method:
func (receiver Type) ServeMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
}
NOTE that the .Parse() methods will accept non-mercury URIs. For example:
err := request.Parse("gemini://example.com/apple/banana/cherry.txt")
func (Request) MarshalText ¶
MarshalText makes Request fit the encoding.TextMarshaler interface.
func (*Request) Parse ¶
Parse parses the input ‘value’ and if valid sets the value of the request.
Note that ‘value’ should NOT include the trailing carriage-return and line-feed.
Example Usage:
var request hg.Request
err := request.Parse("mercury://example.com/apple/banana/cherry.txt")
func (Request) RequestValue ¶
RequestValue returns the value of the request without the trailing "\r\n"
For example, if the full value of the request was:
"mercury://example.com/path/to/file.txt\r\n"
Then RequestValue would return:
"mercury://example.com/path/to/file.txt"
func (Request) Scheme ¶
Scheme returns the Scheme of the URL/URI/IRI in the request.
For example, if the request is:
"mercury://example.com/once/twice/thrice/fource.gmni\r\n"
Then scheme would return:
"mercury"
And, for example, if the request is:
"gemini://example.com/once/twice/thrice/fource.gmni\r\n"
Then scheme would return:
"gemini"
func (Request) String ¶
String returns the full value of the Mercury request. Note that this included the trailing carriage-return and line-feed.
String makes Request fit the fmt.Stringer interface.
func (Request) TCPAddr ¶
TCPAddr returns the TCP-address that is embedded in the request.
Example usage for the Mercury Protocol:
var req hg.Request
// ...
addr, found := req.TCPAddr()
if !found {
return errBadRequest
}
rr, err := hg.DialAndCall(ctx, addr, req)
Example usage for the Gemini Protocol:
var req hg.Request
// ...
addr, found := req.TCPAddr()
if !found {
return errBadRequest
}
rr, err := hg.DialAndCallTLS(ctx, addr, req)
See also:
func (*Request) UnmarshalText ¶
UnmarshalText makes Request fit the encoding.TextUnmarshaler interface.
func (Request) WriteTo ¶
WriteTo writes the value of the Mercury request (including the trailing carriage-return and line-feed) to ‘w’ until there's no more to write or when an error occurs. The return value ‘n’ is the number of bytes written. Any error encountered during the write is also returned.
type ResponseBadRequest ¶
type ResponseBadRequest struct {
// contains filtered or unexported fields
} // 59
ResponseBadRequest represents a Mercury Protocol “59 BAD REQUEST” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseBadRequest) Error ¶
func (receiver ResponseBadRequest) Error() string
func (ResponseBadRequest) Meta ¶
func (receiver ResponseBadRequest) Meta() string
func (ResponseBadRequest) StatusCode ¶
func (receiver ResponseBadRequest) StatusCode() int
func (ResponseBadRequest) StatusText ¶
func (receiver ResponseBadRequest) StatusText() string
type ResponseCGIError ¶
type ResponseCGIError struct {
// contains filtered or unexported fields
} // 42
ResponseCGIError represents a Mercury Protocol “42 CGI ERROR” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseCGIError) Error ¶
func (receiver ResponseCGIError) Error() string
func (ResponseCGIError) Meta ¶
func (receiver ResponseCGIError) Meta() string
func (ResponseCGIError) StatusCode ¶
func (receiver ResponseCGIError) StatusCode() int
func (ResponseCGIError) StatusText ¶
func (receiver ResponseCGIError) StatusText() string
type ResponseCertificateNotAuthorized ¶
type ResponseCertificateNotAuthorized struct {
// contains filtered or unexported fields
} // 61
ResponseCertificateNotAuthorized represents a "61 CERTIFICATE NOT AUTHORIZED" response (Gemini Protocol only). You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseCertificateNotAuthorized) Error ¶
func (receiver ResponseCertificateNotAuthorized) Error() string
func (ResponseCertificateNotAuthorized) Meta ¶
func (receiver ResponseCertificateNotAuthorized) Meta() string
func (ResponseCertificateNotAuthorized) StatusCode ¶
func (receiver ResponseCertificateNotAuthorized) StatusCode() int
func (ResponseCertificateNotAuthorized) StatusText ¶
func (receiver ResponseCertificateNotAuthorized) StatusText() string
type ResponseCertificateNotValid ¶
type ResponseCertificateNotValid struct {
// contains filtered or unexported fields
} // 62
ResponseCertificateNotValid represents a "62 CERTIFICATE NOT VALID" response (Gemini Protocol only). You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseCertificateNotValid) Error ¶
func (receiver ResponseCertificateNotValid) Error() string
func (ResponseCertificateNotValid) Meta ¶
func (receiver ResponseCertificateNotValid) Meta() string
func (ResponseCertificateNotValid) StatusCode ¶
func (receiver ResponseCertificateNotValid) StatusCode() int
func (ResponseCertificateNotValid) StatusText ¶
func (receiver ResponseCertificateNotValid) StatusText() string
type ResponseCertificateRequired ¶
type ResponseCertificateRequired struct {
// contains filtered or unexported fields
} // 60
ResponseCertificateRequired represents a "60 CLIENT CERTIFICATE REQUIRED" response (Gemini Protocol only). You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseCertificateRequired) Error ¶
func (receiver ResponseCertificateRequired) Error() string
func (ResponseCertificateRequired) Meta ¶
func (receiver ResponseCertificateRequired) Meta() string
func (ResponseCertificateRequired) StatusCode ¶
func (receiver ResponseCertificateRequired) StatusCode() int
func (ResponseCertificateRequired) StatusText ¶
func (receiver ResponseCertificateRequired) StatusText() string
type ResponseGone ¶
type ResponseGone struct {
// contains filtered or unexported fields
} // 52
ResponseGone represents a Mercury Protocol “52 GONE” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseGone) Error ¶
func (receiver ResponseGone) Error() string
func (ResponseGone) Meta ¶
func (receiver ResponseGone) Meta() string
func (ResponseGone) StatusCode ¶
func (receiver ResponseGone) StatusCode() int
func (ResponseGone) StatusText ¶
func (receiver ResponseGone) StatusText() string
type ResponseInput ¶
type ResponseInput struct {
// contains filtered or unexported fields
} // 10
ResponseInput represents a Mercury Protocol “10 INPUT” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseInput) Error ¶
func (receiver ResponseInput) Error() string
func (ResponseInput) Meta ¶
func (receiver ResponseInput) Meta() string
func (ResponseInput) StatusCode ¶
func (receiver ResponseInput) StatusCode() int
func (ResponseInput) StatusText ¶
func (receiver ResponseInput) StatusText() string
type ResponseNotFound ¶
type ResponseNotFound struct {
// contains filtered or unexported fields
} // 51
ResponseNotFound represents a Mercury Protocol “51 NOT FOUND” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseNotFound) Error ¶
func (receiver ResponseNotFound) Error() string
func (ResponseNotFound) Meta ¶
func (receiver ResponseNotFound) Meta() string
func (ResponseNotFound) StatusCode ¶
func (receiver ResponseNotFound) StatusCode() int
func (ResponseNotFound) StatusText ¶
func (receiver ResponseNotFound) StatusText() string
type ResponsePermanentFailure ¶
type ResponsePermanentFailure struct {
// contains filtered or unexported fields
} // 50
ResponsePermanentFailure represents a Mercury Protocol “50 PERMANENT FAILURE” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponsePermanentFailure) Error ¶
func (receiver ResponsePermanentFailure) Error() string
func (ResponsePermanentFailure) Meta ¶
func (receiver ResponsePermanentFailure) Meta() string
func (ResponsePermanentFailure) StatusCode ¶
func (receiver ResponsePermanentFailure) StatusCode() int
func (ResponsePermanentFailure) StatusText ¶
func (receiver ResponsePermanentFailure) StatusText() string
type ResponseProxyError ¶
type ResponseProxyError struct {
// contains filtered or unexported fields
} // 43
ResponseProxyError represents a Mercury Protocol “43 PROXY ERROR” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseProxyError) Error ¶
func (receiver ResponseProxyError) Error() string
func (ResponseProxyError) Meta ¶
func (receiver ResponseProxyError) Meta() string
func (ResponseProxyError) StatusCode ¶
func (receiver ResponseProxyError) StatusCode() int
func (ResponseProxyError) StatusText ¶
func (receiver ResponseProxyError) StatusText() string
type ResponseProxyRequestRefused ¶
type ResponseProxyRequestRefused struct {
// contains filtered or unexported fields
} // 53
ResponseProxyRequestRefused represents a Mercury Protocol “53 PROXY REQUEST REFUSED” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseProxyRequestRefused) Error ¶
func (receiver ResponseProxyRequestRefused) Error() string
func (ResponseProxyRequestRefused) Meta ¶
func (receiver ResponseProxyRequestRefused) Meta() string
func (ResponseProxyRequestRefused) StatusCode ¶
func (receiver ResponseProxyRequestRefused) StatusCode() int
func (ResponseProxyRequestRefused) StatusText ¶
func (receiver ResponseProxyRequestRefused) StatusText() string
type ResponseReader ¶
type ResponseReader interface {
io.Closer
Read(ctx context.Context, data []byte) (int, error)
Reader(ctx context.Context) io.Reader
ReadHeader(ctx context.Context, statusCode *int, meta any) (int, error)
// ServerCertificate returns the server's leaf certificate from the TLS handshake.
// Returns nil for plain (non-TLS) connections or if no server cert was presented.
ServerCertificate() *x509.Certificate
// ClientCertificate returns the client certificate (including private-key)
// that was presented during the TLS handshake.
// Returns nil if no client cert was used, or for plain (non-TLS) connections.
ClientCertificate() *tls.Certificate
}
ResponseReader is used by a Handler to read a Mercury Protocol response.
To get io.Reader version of ResponseReader call its `Reader` method. For example:
var rr hg.ResponseReader var err error rr, err = hg.DialAndCall(ctx, "example.com:1961", request) // ... var reader io.Reader = rr.Reader(ctx)
Alternatively, to use a read-method with a context, just do something similar to:
n, err := rr.Read(ctx, p)
Auto-Reading Header ¶
If Read is called before ReadHeader, it will automatically read and consume the response header. If the status code is not "20 SUCCESS", Read returns an error that can be type-switched or used with errors.As to extract the status code and meta. For example:
n, err := rr.Read(ctx, buf)
if nil != err {
var notFound hg.ResponseNotFound
if errors.As(err, ¬Found) {
fmt.Println("not found:", notFound.Meta())
}
}
The possible error types are:
- ResponseBadRequest
- ResponseCertificateNotAuthorized
- ResponseCertificateNotValid
- ResponseCertificateRequired
- ResponseCGIError
- ResponseGone
- ResponseInput
- ResponseNotFound
- ResponsePermanentFailure
- ResponseProxyError
- ResponseProxyRequestRefused
- ResponseRedirectPermanent
- ResponseRedirectTemporary
- ResponseSensitiveInput
- ResponseServerUnavailable
- ResponseSlowDown
- ResponseTemporaryFailure
- UnknownResponse
Each has StatusCode() and Meta() methods.
Note that once Read has consumed the header, calling ReadHeader will return an error. If you need to inspect the header before reading the body, call ReadHeader first.
func Call ¶
Call uses the TCP connection provided by 'conn' and (speaking the Mercury Protocol) sends the request given by 'request'.
The context 'ctx' controls the lifetime of the request write. If 'ctx' is nil, context.Background() is used. If 'ctx' has a deadline, it is applied as a write deadline on the connection.
What is given by 'request' might be a Request containing something like: "mercury://example.com/path/to/file.txt"
An example of using this might be:
conn, err := net.Dial("tcp", addr)
if nil != err {
return err
}
ctx := context.Background()
rr, err := hg.Call(ctx, conn, request)
See also:
func DialAndCall ¶
DialAndCall makes a TCP connection to the TCP address given by 'addr', and (speaking the Mercury Protocol) sends the request given by 'request'.
The context 'ctx' controls the lifetime of the dial and the request write. If 'ctx' is nil, context.Background() is used. To apply a timeout, use context.WithTimeout or context.WithDeadline.
What is given by 'addr' might be something like: "11.22.33.44:1961", or "example.com:1961"
What is given by 'request' might be a Request containing something like: "mercury://example.com/path/to/file.txt\r\n"
An example of using this might be:
var uri string = "mercury://example.com/once/twice/thrice/fource.gmni"
var request hg.Request
err := request.Parse(uri)
if nil != err {
return err
}
addr, found := request.TCPAddr()
if !found {
return errBadRequest
}
ctx := context.Background()
rr, err := hg.DialAndCall(ctx, addr, request)
See also:
func DialAndCallTLS ¶
func DialAndCallTLS(ctx context.Context, addr string, request Request, tlsHandler TLSHandler) (ResponseReader, error)
DialAndCallTLS makes a TLS connection to the TCP address given by 'addr', and sends the request given by 'request'.
This can be used to speak protocols that layer on TLS (such as the Gemini Protocol).
The context 'ctx' controls the lifetime of the dial and the request write. If 'ctx' is nil, context.Background() is used. To apply a timeout, use context.WithTimeout or context.WithDeadline.
The 'tlsHandler' controls server certificate verification and client certificate selection. Passing nil means: accept any server certificate, no client cert.
What is given by 'addr' might be something like: "11.22.33.44:1965", or "example.com:1965"
What is given by 'request' might be a Request containing something like: "gemini://example.com/path/to/file.txt\r\n"
An example of using this might be:
var uri string = "gemini://example.com/once/twice/thrice/fource.gmni"
var request hg.Request
err := request.Parse(uri)
if nil != err {
return err
}
addr, found := request.TCPAddr()
if !found {
return errBadRequest
}
ctx := context.Background()
rr, err := hg.DialAndCallTLS(ctx, addr, request, nil)
See also:
func DialAndCallURL ¶
func DialAndCallURL(ctx context.Context, url string, tlsHandler TLSHandler) (ResponseReader, error)
DialAndCallURL makes a TCP connection to the TCP address implied by the URL. and (speaking the Mercury Protocol or the Gemini Protocol) sends the request implied by the URL.
The context 'ctx' controls the lifetime of the dial and the request write. If 'ctx' is nil, context.Background() is used. To apply a timeout, use context.WithTimeout or context.WithDeadline.
The 'tlsHandler' controls server certificate verification and client certificate selection for gemini:// (TLS) URLs. For mercury:// URLs it is ignored. Passing nil means: accept any server certificate, no client cert.
An example of using this for a Gemini URL might be:
var url string = "gemini://example.com/once/twice/thrice/fource.gmni" ctx := context.Background() rr, err := hg.DialAndCallURL(ctx, url, nil)
Using it with a Mercury URL looks the same:
var url string = "mercury://example.com/once/twice/thrice/fource.gmni" ctx := context.Background() rr, err := hg.DialAndCallURL(ctx, url, nil)
See also:
type ResponseRedirectPermanent ¶
type ResponseRedirectPermanent struct {
// contains filtered or unexported fields
} // 31
ResponseRedirectPermanent represents a Mercury Protocol “31 REDIRECT - PERMANENT” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseRedirectPermanent) Error ¶
func (receiver ResponseRedirectPermanent) Error() string
func (ResponseRedirectPermanent) Meta ¶
func (receiver ResponseRedirectPermanent) Meta() string
func (ResponseRedirectPermanent) StatusCode ¶
func (receiver ResponseRedirectPermanent) StatusCode() int
func (ResponseRedirectPermanent) StatusText ¶
func (receiver ResponseRedirectPermanent) StatusText() string
type ResponseRedirectTemporary ¶
type ResponseRedirectTemporary struct {
// contains filtered or unexported fields
} // 30
ResponseRedirectTemporary represents a Mercury Protocol “30 REDIRECT - TEMPORARY” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseRedirectTemporary) Error ¶
func (receiver ResponseRedirectTemporary) Error() string
func (ResponseRedirectTemporary) Meta ¶
func (receiver ResponseRedirectTemporary) Meta() string
func (ResponseRedirectTemporary) StatusCode ¶
func (receiver ResponseRedirectTemporary) StatusCode() int
func (ResponseRedirectTemporary) StatusText ¶
func (receiver ResponseRedirectTemporary) StatusText() string
type ResponseSensitiveInput ¶
type ResponseSensitiveInput struct {
// contains filtered or unexported fields
} // 11
ResponseSensitiveInput represents a Mercury Protocol “11 SENSITIVE INPUT” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseSensitiveInput) Error ¶
func (receiver ResponseSensitiveInput) Error() string
func (ResponseSensitiveInput) Meta ¶
func (receiver ResponseSensitiveInput) Meta() string
func (ResponseSensitiveInput) StatusCode ¶
func (receiver ResponseSensitiveInput) StatusCode() int
func (ResponseSensitiveInput) StatusText ¶
func (receiver ResponseSensitiveInput) StatusText() string
type ResponseServerUnavailable ¶
type ResponseServerUnavailable struct {
// contains filtered or unexported fields
} // 41
ResponseServerUnavailable represents a Mercury Protocol “41 SERVER UNAVAILABLE” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseServerUnavailable) Error ¶
func (receiver ResponseServerUnavailable) Error() string
func (ResponseServerUnavailable) Meta ¶
func (receiver ResponseServerUnavailable) Meta() string
func (ResponseServerUnavailable) StatusCode ¶
func (receiver ResponseServerUnavailable) StatusCode() int
func (ResponseServerUnavailable) StatusText ¶
func (receiver ResponseServerUnavailable) StatusText() string
type ResponseSlowDown ¶
type ResponseSlowDown struct {
// contains filtered or unexported fields
} // 44
ResponseSlowDown represents a Mercury Protocol “44 SLOW DOWN” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseSlowDown) Error ¶
func (receiver ResponseSlowDown) Error() string
func (ResponseSlowDown) Meta ¶
func (receiver ResponseSlowDown) Meta() string
func (ResponseSlowDown) StatusCode ¶
func (receiver ResponseSlowDown) StatusCode() int
func (ResponseSlowDown) StatusText ¶
func (receiver ResponseSlowDown) StatusText() string
type ResponseTemporaryFailure ¶
type ResponseTemporaryFailure struct {
// contains filtered or unexported fields
} // 40
ResponseTemporaryFailure represents a Mercury Protocol “40 TEMPORARY FAILURE” response. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (ResponseTemporaryFailure) Error ¶
func (receiver ResponseTemporaryFailure) Error() string
func (ResponseTemporaryFailure) Meta ¶
func (receiver ResponseTemporaryFailure) Meta() string
func (ResponseTemporaryFailure) StatusCode ¶
func (receiver ResponseTemporaryFailure) StatusCode() int
func (ResponseTemporaryFailure) StatusText ¶
func (receiver ResponseTemporaryFailure) StatusText() string
type ResponseWriter ¶
type ResponseWriter interface {
Write(ctx context.Context, p []byte) (n int, err error)
Writer(ctx context.Context) io.Writer
WriteHeader(ctx context.Context, statusCode int, meta string) (int, error)
}
ResponseWriter is used by a Handler to construct a Mercury Protocol response.
For example:
func serveMercury(ctx context.Context, w hg.ResponseWriter, r hg.Request) {
// ...
}
Notice that the first parameter is a ResponseWriter.
type Server ¶
type Server struct {
Addr string // TCP address to listen on; if empty defaults to ":1961"
Handler Handler // handler to invoke; if nil defaults to hg.DebugHandler
Logger Logger
// ReadTimeout is the maximum duration for reading the request line.
// If zero, no timeout is applied and a slow client can hold a
// connection open indefinitely (slowloris DoS vector).
ReadTimeout time.Duration
// HandlerTimeout is the default maximum duration for a handler to complete.
// If a handler implements TimeoutHandler, its Timeout value takes precedence.
// If zero, no timeout is applied and handlers may run indefinitely.
HandlerTimeout time.Duration
// MaxConnections limits the number of concurrent connections the server will handle.
// If zero or negative, no limit is applied.
MaxConnections int
// contains filtered or unexported fields
}
Server is a Mercury Protocol server.
For a simple example:
package main
import (
"github.com/reiver/go-hg"
)
func main() {
var handler hg.Handler = hg.DebugHandler
server := &hg.Server{
Addr:":1961",
Handler:handler,
}
err := server.ListenAndServe()
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
}
func (*Server) ListenAndServe ¶
ListenAndServe listens on the TCP network address 'server.Addr' and then spawns a call to the ServeMercury method on the 'server.Handler' to serve each incoming connection.
For a simple example:
package main
import (
"github.com/reiver/go-hg"
)
func main() {
var handler hg.Handler = hg.DebugHandler
server := &hg.Server{
Addr:":1961",
Handler:handler,
}
err := server.ListenAndServe()
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
}
func (*Server) Serve ¶
Serve accepts an incoming Mercury Protocol client connection on the net.Listener ‘listener’.
For a simple example:
package main
import (
"github.com/reiver/go-hg"
)
func main() {
listener, err := net.Listen("tcp", ":1961")
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
var handler hg.Handler = hg.DebugHandler
server := &hg.Server{
Handler:handler,
}
err = server.Serve(listener)
if nil != err {
//@TODO: Handle this error better.
panic(err)
}
}
func (*Server) Shutdown ¶
Shutdown gracefully shuts down the server.
It stops accepting new connections, then waits for active connections to finish. The provided context controls how long Shutdown is willing to wait — if the context expires before all connections are done, Shutdown returns the context's error.
Shutdown is safe to call multiple times — only the first call triggers the shutdown.
func (*Server) Wait ¶
func (receiver *Server) Wait()
Wait blocks until all active connection handlers have finished.
When Shutdown's context expires, Shutdown force-closes all connections and returns immediately — but the handler goroutines may still be running their cleanup (defers, logging, untracking). Wait blocks until those goroutines have fully exited.
Typical usage:
err := server.Shutdown(ctx)
if err != nil {
// Shutdown timed out, but goroutines are still unwinding.
server.Wait()
}
If Shutdown completed without error (all connections drained before the context expired), Wait returns immediately.
type TLSConfig ¶
type TLSConfig struct {
VerifyServerCertificateFunc func(hostname string, rawCerts [][]byte) error
ClientCertificateFunc func(hostname string) *tls.Certificate
}
TLSConfig is a TLSHandler implementation built from function fields. Nil fields are treated as no-ops (accept any server, no client cert).
func (TLSConfig) ClientCertificate ¶
func (receiver TLSConfig) ClientCertificate(hostname string) *tls.Certificate
type TLSHandler ¶
type TLSHandler interface {
// VerifyServerCertificate is called after the TLS handshake with the server's certificate chain (DER-encoded, leaf first).
// rawCerts may be empty if the server sends no certificates.
// Return nil to accept the connection, or an error to reject it.
VerifyServerCertificate(hostname string, rawCerts [][]byte) error
// ClientCertificate is called when a client certificate is needed.
// 'hostname' is the host being connected to without TCP-port.
// Return nil to proceed without presenting one.
ClientCertificate(hostname string) *tls.Certificate
}
TLSHandler handles TLS-layer decisions during connection setup.
Used only for Gemini Protocol. Ignored for the Mercury Protocol.
See also:
var DefaultVerifier TLSHandler = defaultVerifier{}
DefaultVerifier is a TLSHandler that applies CA verification only when the server's certificate chains to a system-trusted CA. Self-signed certs are accepted without CA verification (for TOFU workflows).
Behavior:
- Self-signed cert (CheckSignatureFrom succeeds) -> accepted
- CA-signed cert, valid -> accepted
- CA-signed cert, expired or wrong hostname -> rejected
- No certificates presented -> rejected
type TimeoutHandler ¶
TimeoutHandler is an optional interface that a Handler may implement to declare how long it should be allowed to run.
If Timeout returns a positive duration, the server will apply that as a deadline on the context passed to ServeMercury.
If Timeout returns zero or a negative duration, no timeout is applied (the handler is considered long-lived).
Handlers that do not implement this interface fall back to Server.HandlerTimeout.
type UnknownResponse ¶
type UnknownResponse struct {
// contains filtered or unexported fields
}
UnknownResponse represents an unknown response that this package doesn't have a type for. You might get this from hg.ErrorResponse() or called the .Read(ctx, data) method on a hg.ResponseReader
func (UnknownResponse) Error ¶
func (receiver UnknownResponse) Error() string
func (UnknownResponse) Meta ¶
func (receiver UnknownResponse) Meta() string
func (UnknownResponse) StatusCode ¶
func (receiver UnknownResponse) StatusCode() int
func (UnknownResponse) StatusText ¶
func (receiver UnknownResponse) StatusText() string
type UserDirHandler ¶
type UserDirHandler struct {
// AllowSymLinks controls whether symbolic links inside a user's mercury_public
// directory are followed. If false (the default), requests that resolve to a
// symlink or pass through a symlink are rejected with a not-found response.
AllowSymLinks bool
Logger Logger
}
UserDirHandler is a Mercury Protocol handler for tilde (~) capsule sites.
Makes things like this:
mercury://example.com/~username/
Get mapped to:
/home/username/mercury_public/default.gmni
And makes things like this:
mercury://example.com/~username/once/twice/thrice/fource.txt
Get mapped to:
/home/username/mercury_public/once/twice/thrice/fource.txt
func (*UserDirHandler) ServeMercury ¶
func (receiver *UserDirHandler) ServeMercury(ctx context.Context, w ResponseWriter, r Request)
Source Files
¶
- client.go
- consts.go
- debughandler.go
- defaultmeta.go
- defaulttcpport.go
- discardlogger.go
- errorresponse.go
- errors.go
- filesystemhandler.go
- handle.go
- handler.go
- handlerfunc.go
- infermediatype.go
- logger.go
- mustlogger.go
- parsetildedir.go
- reqpath2fspath.go
- request.go
- responsereader.go
- responses.go
- responsewriter.go
- schemes.go
- serve.go
- server.go
- statuscodefromrunes.go
- statuses.go
- tls.go
- tlshandler.go
- userdirhandler.go