grim/hgkeeper
Clone
Summary
Browse
Changes
Graph
Update the documentation for additional OpenSSH integration and fix some other typoes
2022-03-06, Gary Kramlich
df734a54a97c
Update the documentation for additional OpenSSH integration and fix some other typoes
//go:generate esc -o files.go -pkg hgweb -include files\/.+ -prefix files/ .
package
hgweb
import
(
"io/ioutil"
"net/http"
"net/http/cgi"
"os"
"path/filepath"
"text/template"
log
"github.com/sirupsen/logrus"
"keep.imfreedom.org/grim/hgkeeper/access"
"keep.imfreedom.org/grim/hgkeeper/hg"
hgkHttp
"keep.imfreedom.org/grim/hgkeeper/http"
)
type
Server
struct
{
listenAddr
string
server
*
http
.
Server
configPath
string
cgiPath
string
cacheSize
int
externalHostname
string
externalPort
string
}
func
NewServer
(
listenAddr
string
,
cacheSize
int
,
externalHostname
,
externalPort
string
)
(
*
Server
,
error
)
{
return
&
Server
{
listenAddr
:
listenAddr
,
cacheSize
:
cacheSize
,
server
:
&
http
.
Server
{
Addr
:
listenAddr
,
},
externalHostname
:
externalHostname
,
externalPort
:
externalPort
,
},
nil
}
func
(
s
*
Server
)
createConfig
()
error
{
configPath
,
err
:=
ioutil
.
TempFile
(
""
,
"hgkeeper-hgweb-*.config"
)
if
err
!=
nil
{
return
err
}
defer
configPath
.
Close
()
t
:=
template
.
Must
(
template
.
New
(
"hgweb-config"
).
Parse
(
FSMustString
(
false
,
"/hgweb.config"
)))
data
:=
map
[
string
]
string
{
"HGWEB_ACCESS_CONFIG"
:
access
.
HgwebConfigPath
(),
"SITE_HGRC"
:
filepath
.
Join
(
access
.
AdminRepoPath
(),
"site.hgrc"
),
"GLOBAL_HGRC"
:
filepath
.
Join
(
access
.
AdminRepoPath
(),
"config/hgrc"
),
}
if
err
:=
t
.
Execute
(
configPath
,
data
);
err
!=
nil
{
return
err
}
s
.
configPath
=
configPath
.
Name
()
return
nil
}
func
(
s
*
Server
)
createCGI
()
error
{
cgiPath
,
err
:=
ioutil
.
TempFile
(
""
,
"hgkeeper-hgweb-*.cgi"
)
if
err
!=
nil
{
return
err
}
defer
cgiPath
.
Close
()
// make the cgi file executable
if
err
:=
cgiPath
.
Chmod
(
0755
);
err
!=
nil
{
return
err
}
// create a template based for the cgi file
t
:=
template
.
Must
(
template
.
New
(
"cgi"
).
Parse
(
FSMustString
(
false
,
"/hgweb.cgi"
)))
// create our data
data
:=
map
[
string
]
string
{
"HGWEB_CONFIG"
:
s
.
configPath
,
}
if
err
:=
t
.
Execute
(
cgiPath
,
data
);
err
!=
nil
{
return
err
}
s
.
cgiPath
=
cgiPath
.
Name
()
return
nil
}
func
(
s
*
Server
)
Listen
()
error
{
if
err
:=
s
.
createConfig
();
err
!=
nil
{
return
err
}
if
err
:=
s
.
createCGI
();
err
!=
nil
{
return
err
}
cache
,
err
:=
newCache
(
s
.
cacheSize
)
if
err
!=
nil
{
return
err
}
templatesDir
,
err
:=
hg
.
TemplatesDir
()
if
err
!=
nil
{
return
err
}
staticPath
:=
filepath
.
Join
(
templatesDir
,
"static"
)
log
.
Infof
(
"serving static files from %s"
,
staticPath
)
fileServer
:=
http
.
FileServer
(
http
.
Dir
(
staticPath
))
mux
:=
http
.
NewServeMux
()
if
s
.
externalHostname
!=
""
{
mux
.
Handle
(
"/ssh/authorized_keys"
,
hgkHttp
.
AuthorizedKeysHandler
(
s
.
externalHostname
,
s
.
externalPort
))
log
.
Infof
(
"added /ssh/authorized_keys endpoint with external hostname %s and export port %s"
,
s
.
externalHostname
,
s
.
externalPort
)
}
else
{
log
.
Infof
(
"no external hostname specified, not adding /ssh/authorized_keys endpoint"
)
}
mux
.
Handle
(
"/static/"
,
http
.
StripPrefix
(
"/static"
,
fileServer
))
mux
.
Handle
(
"/"
,
&
cgi
.
Handler
{
Path
:
s
.
cgiPath
})
enableCache
:=
false
if
enableCache
{
s
.
server
.
Handler
=
Logger
(
cache
.
middleware
(
mux
))
}
else
{
s
.
server
.
Handler
=
Logger
(
mux
)
}
log
.
Infof
(
"http listening on %s"
,
s
.
listenAddr
)
return
s
.
server
.
ListenAndServe
()
}
func
(
s
*
Server
)
Close
()
{
if
err
:=
os
.
Remove
(
s
.
cgiPath
);
err
!=
nil
{
log
.
Warnf
(
"failed to remove temporary cgi file %q: %v"
,
s
.
cgiPath
,
err
)
}
if
err
:=
s
.
server
.
Close
();
err
!=
nil
{
log
.
Warnf
(
"failed to shutdown http server: %v"
,
err
)
}
}