Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass hostname to all html templates #133

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 30 additions & 12 deletions golink.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,19 +285,41 @@ type deleteData struct {
var xsrfKey string

func init() {
homeTmpl = template.Must(template.ParseFS(embeddedFS, "tmpl/base.html", "tmpl/home.html"))
detailTmpl = template.Must(template.ParseFS(embeddedFS, "tmpl/base.html", "tmpl/detail.html"))
successTmpl = template.Must(template.ParseFS(embeddedFS, "tmpl/base.html", "tmpl/success.html"))
helpTmpl = template.Must(template.ParseFS(embeddedFS, "tmpl/base.html", "tmpl/help.html"))
allTmpl = template.Must(template.ParseFS(embeddedFS, "tmpl/base.html", "tmpl/all.html"))
deleteTmpl = template.Must(template.ParseFS(embeddedFS, "tmpl/base.html", "tmpl/delete.html"))
opensearchTmpl = template.Must(template.ParseFS(embeddedFS, "tmpl/opensearch.xml"))
homeTmpl = newTemplate("base.html", "home.html")
detailTmpl = newTemplate("base.html", "detail.html")
successTmpl = newTemplate("base.html", "success.html")
helpTmpl = newTemplate("base.html", "help.html")
allTmpl = newTemplate("base.html", "all.html")
deleteTmpl = newTemplate("base.html", "delete.html")
opensearchTmpl = newTemplate("opensearch.xml")

b := make([]byte, 24)
rand.Read(b)
xsrfKey = base64.StdEncoding.EncodeToString(b)
}

var tmplFuncs = template.FuncMap{
"go": func() string {
return *hostname
},
}

// newTemplate creates a new template with the specified files in the tmpl directory.
// The first file name is used as the template name,
// and tmplFuncs are registered as available funcs.
// This func panics if unable to parse files.
func newTemplate(files ...string) *template.Template {
if len(files) == 0 {
return nil
}
tf := make([]string, 0, len(files))
for _, f := range files {
tf = append(tf, "tmpl/"+f)
}
t := template.New(files[0]).Funcs(tmplFuncs)
return template.Must(t.ParseFS(embeddedFS, tf...))
}

// initStats initializes the in-memory stats counter with counts from db.
func initStats() error {
stats.mu.Lock()
Expand Down Expand Up @@ -473,12 +495,8 @@ func serveHelp(w http.ResponseWriter, _ *http.Request) {
}

func serveOpenSearch(w http.ResponseWriter, _ *http.Request) {
type opensearchData struct {
Hostname string
}

w.Header().Set("Content-Type", "application/opensearchdescription+xml")
opensearchTmpl.Execute(w, opensearchData{Hostname: *hostname})
opensearchTmpl.Execute(w, nil)
}

func serveGo(w http.ResponseWriter, r *http.Request) {
Expand Down
2 changes: 1 addition & 1 deletion tmpl/all.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ <h2 class="text-xl font-bold pt-6 pb-2">All Links ({{ len . }} total)</h2>
<tr class="flex hover:bg-gray-100 group border-b border-gray-200">
<td class="flex-1 p-2">
<div class="flex">
<a class="flex-1 hover:text-blue-500 hover:underline" href="/{{ .Short }}">go/{{ .Short }}</a>
<a class="flex-1 hover:text-blue-500 hover:underline" href="/{{ .Short }}">{{go}}/{{ .Short }}</a>
<a class="flex items-center px-2 invisible group-hover:visible" title="Link Details" href="/.detail/{{ .Short }}">
<svg class="hover:fill-blue-500" xmlns="http://www.w3.org/2000/svg" height="1.3em" viewBox="0 0 24 24" width="1.3em" fill="#000000" stroke-width="2"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>
</a>
Expand Down
4 changes: 2 additions & 2 deletions tmpl/base.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!doctype html>
<html lang="en">
<head>
<title>go/</title>
<title>{{go}}/</title>
<link rel="stylesheet" href="/.static/base.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="search" type="application/opensearchdescription+xml" title="searchTitle" href="/.opensearch" />
Expand All @@ -11,7 +11,7 @@
<body class="flex flex-col min-h-screen">
<div class="bg-gray-100 border-b border-gray-200 pt-4 pb-2 mb-6">
<header class="container mx-auto px-4">
<h1 class="text-2xl font-bold pb-1"><a href="/">go/</a></h1>
<h1 class="text-2xl font-bold pb-1"><a href="/">{{go}}/</a></h1>
A private shortlink service for your tailnet
</header>
</div>
Expand Down
4 changes: 2 additions & 2 deletions tmpl/delete.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{{ define "main" }}
<h2 class="text-xl font-bold pb-2">Link go/{{.Short}} Deleted</h2>
<h2 class="text-xl font-bold pb-2">Link {{go}}/{{.Short}} Deleted</h2>

<p class="py-4">Deleted this by mistake? You can recreate the same link below.</p>

<form method="POST" action="/">
<input type="hidden" name="xsrf" value="{{ .XSRF }}" />
<div class="flex flex-wrap">
<div class="flex">
<label for=short class="flex my-2 px-2 items-center bg-gray-100 border border-r-0 border-gray-300 rounded-l-md text-gray-700">http://go/</label>
<label for=short class="flex my-2 px-2 items-center bg-gray-100 border border-r-0 border-gray-300 rounded-l-md text-gray-700">http://{{go}}/</label>
<input id=short name=short required type=text size=15 placeholder="shortname" value="{{.Short}}" pattern="\w[\w\-\.]*" title="Must start with letter or number; may contain letters, numbers, dashes, and periods."
class="p-2 my-2 rounded-r-md border-gray-300 placeholder:text-gray-400 disabled:bg-gray-100">
<span class="flex m-2 items-center">&rarr;</span>
Expand Down
4 changes: 2 additions & 2 deletions tmpl/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ <h2 class="text-xl font-bold pb-2">Link Details</h2>
<input type="hidden" name="xsrf" value="{{ .XSRF }}" />
<div class="flex flex-wrap">
<div class="flex">
<label for=short class="flex my-2 px-2 items-center bg-gray-100 border border-r-0 border-gray-300 rounded-l-md text-gray-700">http://go/</label>
<label for=short class="flex my-2 px-2 items-center bg-gray-100 border border-r-0 border-gray-300 rounded-l-md text-gray-700">http://{{go}}/</label>
<input id=short name=short required type=text size=15 placeholder="shortname" value="{{.Link.Short}}" pattern="\w[\w\-\.]*" title="Must start with letter or number; may contain letters, numbers, dashes, and periods."
class="p-2 my-2 rounded-r-md border-gray-300 placeholder:text-gray-400 disabled:bg-gray-100">
<span class="flex m-2 items-center">&rarr;</span>
Expand Down Expand Up @@ -40,7 +40,7 @@ <h3 class="text-lg font-bold pb-2 pt-4 text-red-500">Danger Zone</h3>
{{ else }}
<dl>
<dt class="text-sm font-bold mt-6">Name</dt>
<dd><a class="text-blue-600 hover:underline" href="/{{.Link.Short}}">go/{{.Link.Short}}</a></dd>
<dd><a class="text-blue-600 hover:underline" href="/{{.Link.Short}}">{{go}}/{{.Link.Short}}</a></dd>

<dt class="text-sm font-bold mt-6">Destination</dt>
<dd>{{.Link.Long}}</dd>
Expand Down
48 changes: 24 additions & 24 deletions tmpl/help.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{{ define "main" }}
<article class="prose max-w-5xl">
<p>
go links provide short, memorable links for the websites you and your team use most.
{{go}} links provide short, memorable links for the websites you and your team use most.

<h2>Creating go links</h2>
<h2>Creating {{go}} links</h2>

<p>
All go links have a <strong>short name</strong> and a <strong>destination link</strong> that the go link points to.
All {{go}} links have a <strong>short name</strong> and a <strong>destination link</strong> that the {{go}} link points to.
Some notes on short names:

<ul>
<li>names must start with a letter or number
<li>names may contain letters, numbers, hyphens, and periods
<li>names are <strong>not</strong> case-sensitive (go/foo is the same as go/FOO)
<li>hyphens are ignored when resolving links (go/meetingnotes is the same as go/meeting-notes)
<li>names are <strong>not</strong> case-sensitive ({{go}}/foo is the same as {{go}}/FOO)
<li>hyphens are ignored when resolving links ({{go}}/meetingnotes is the same as {{go}}/meeting-notes)
</ul>

<p>
Expand All @@ -25,26 +25,26 @@ <h2>Creating go links</h2>
<h2>Resolving links</h2>

<p>
When logged in to your Tailscale network, go links can be entered directly into any browser or command line utility such as curl.
When logged in to your Tailscale network, {{go}} links can be entered directly into any browser or command line utility such as curl.
You do not need any additional browser extensions.

<p>
Any additional path provided after the short name will be added to the end of the destination link.
For example, if <strong>go/who</strong> goes to your company directory at <strong>http://directory/</strong>,
then <strong>go/who/amelie</strong> will go to <strong>http://directory/amelie</strong>.
For example, if <strong>{{go}}/who</strong> goes to your company directory at <strong>http://directory/</strong>,
then <strong>{{go}}/who/amelie</strong> will go to <strong>http://directory/amelie</strong>.

<p>
<a href="#advanced">Advanced destination links</a> allow you to further customize this behavior.

<h2 id="advanced">Advanced destination links</h2>

<p>
To have more control over how go links are resolved, destination links can use <a href="https://pkg.go.dev/text/template">Go template syntax</a>.
To have more control over how {{go}} links are resolved, destination links can use <a href="https://pkg.go.dev/text/template">Go template syntax</a>.
Templates are provided a data structure with the following fields:

<ul>
<li><code>.Path</code> is the remaining path value after the short name (without a leading slash).
For the link <strong>go/who/amelie</strong>, the value of <code>.Path</code> is <code>amelie</code>.
For the link <strong>{{go}}/who/amelie</strong>, the value of <code>.Path</code> is <code>amelie</code>.
<li><code>.Now</code> is a <a href="https://pkg.go.dev/time#Time">time.Time</a> value representing the current date and time.
<li><code>.User</code> is the current user resolving the link.
This is the email address of the user or <code>{username}@github</code> for tailnets that use GitHub authentication.
Expand All @@ -61,34 +61,34 @@ <h2 id="advanced">Advanced destination links</h2>

<p>
The most common use of advanced destination links is to put the additional path in a custom location in the destination link.
For example, you might set the destination for <strong>go/search</strong> to:
For example, you might set the destination for <strong>{{go}}/search</strong> to:

<pre>{{`https://www.google.com/{{if .Path}}search?q={{QueryEscape .Path}}{{end}}`}}</pre>

When a user visits <strong>go/search</strong> with no additional path, they will be directed to <a href="https://www.google.com/">https://www.google.com/</a>.
If they include an additional path like <strong>go/search/pangolins</strong>, they will be directed to <a href="https://www.google.com/search?q=pangolins">https://www.google.com/search?q=pangolins</a>.
When a user visits <strong>{{go}}/search</strong> with no additional path, they will be directed to <a href="https://www.google.com/">https://www.google.com/</a>.
If they include an additional path like <strong>{{go}}/search/pangolins</strong>, they will be directed to <a href="https://www.google.com/search?q=pangolins">https://www.google.com/search?q=pangolins</a>.

<h3>Examples</h3>

<table>
<tr>
<td>Include path in query</td>
<td>go/search</td>
<td>{{go}}/search</td>
<td>{{`https://cloudsearch.google.com/{{if .Path}}cloudsearch/search?q={{QueryEscape .Path}}{{end}}`}}</td>
</tr>
<tr>
<td>Include path in destination path</td>
<td>go/slack</td>
<td>{{go}}/slack</td>
<td>{{`https://company.slack.com/{{if .Path}}channels/{{PathEscape .Path}}{{end}}`}}</td>
</tr>
<tr>
<td>Include path in hostname</td>
<td>go/varz</td>
<td>{{go}}/varz</td>
<td>{{`http://{{if .Path}}{{.Path}}{{else}}host{{end}}.example/debug/varz`}}</td>
</tr>
<tr>
<td>Include today's date in wiki page</td>
<td>go/today</td>
<td>{{go}}/today</td>
<td>{{`http://wiki/{{.Now.Format "01-02-2006"}}`}}</td>
</tr>
</table>
Expand All @@ -101,8 +101,8 @@ <h2 id="api">Application Programming Interface (API)</h2>
<p>
Include a "+" after a link to get information about a link without resolving it:

<pre>{{`$ curl -L go/search+
{
<pre>$ curl -L {{go}}/search+
{{`{
"Short": "search",
"Long": "https://cloudsearch.google.com/{{if .Path}}cloudsearch/search?q={{QueryEscape .Path}}{{end}}",
"Created": "2022-06-08T04:27:32.829906577Z",
Expand All @@ -113,19 +113,19 @@ <h2 id="api">Application Programming Interface (API)</h2>
</pre>

<p>
Visit <a href="/.export">go/.export</a> to export all saved links and their metadata in <a href="https://jsonlines.org/">JSON Lines format</a>.
Visit <a href="/.export">{{go}}/.export</a> to export all saved links and their metadata in <a href="https://jsonlines.org/">JSON Lines format</a>.
This is useful to create data snapshots that can be restored later.

<pre>{{`$ curl -L go/.export
{"Short":"go","Long":"http://go","Created":"2022-05-31T13:04:44.741457796-07:00","LastEdit":"2022-05-31T13:04:44.741457796-07:00","Owner":"amelie@example.com","Clicks":1}
<pre>$ curl -L {{go}}/.export
{{`{"Short":"go","Long":"http://go","Created":"2022-05-31T13:04:44.741457796-07:00","LastEdit":"2022-05-31T13:04:44.741457796-07:00","Owner":"amelie@example.com","Clicks":1}
{"Short":"slack","Long":"https://company.slack.com/{{if .Path}}channels/{{PathEscape .Path}}{{end}}","Created":"2022-06-17T18:05:43.562948451Z","LastEdit":"2022-06-17T18:06:35.811398Z","Owner":"amelie@example.com","Clicks":4}`}}
</pre>

<p>
Create a new link by sending a POST request with a <code>short</code> and <code>long</code> value:

<pre>{{`$ curl -L -H Sec-Golink:1 -d short=cs -d long=https://cs.github.com/ go
{"Short":"cs","Long":"https://cs.github.com/","Created":"2022-06-03T22:15:29.993978392Z","LastEdit":"2022-06-03T22:15:29.993978392Z","Owner":"amelie@example.com"}`}}
<pre>$ curl -L -H Sec-Golink:1 -d short=cs -d long=https://cs.github.com/ {{go}}
{{`{"Short":"cs","Long":"https://cs.github.com/","Created":"2022-06-03T22:15:29.993978392Z","LastEdit":"2022-06-03T22:15:29.993978392Z","Owner":"amelie@example.com"}`}}
</pre>

</article>
Expand Down
6 changes: 3 additions & 3 deletions tmpl/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<h2 class="text-xl font-bold pb-2">Create a new link</h2>

{{ with .Long }}
<p class="">Did you mean <a class="text-blue-600 hover:underline" href="{{.}}">{{.}}</a> ? Create a go link for it now:</p>
<p class="">Did you mean <a class="text-blue-600 hover:underline" href="{{.}}">{{.}}</a> ? Create a {{go}} link for it now:</p>
{{ end }}
<form method="POST" action="/" class="flex flex-wrap">
<input type="hidden" name="xsrf" value="{{ .XSRF }}" />
<div class="flex">
<label for=short class="flex my-2 px-2 items-center bg-gray-100 border border-r-0 border-gray-300 rounded-l-md text-gray-700">http://go/</label>
<label for=short class="flex my-2 px-2 items-center bg-gray-100 border border-r-0 border-gray-300 rounded-l-md text-gray-700">http://{{go}}/</label>
<input id=short name=short required type=text size=15 placeholder="shortname" value="{{.Short}}" pattern="\w[\w\-\.]*" title="Must start with letter or number; may contain letters, numbers, dashes, and periods."
class="p-2 my-2 rounded-r-md border-gray-300 placeholder:text-gray-400">
<span class="flex m-2 items-center">&rarr;</span>
Expand All @@ -29,7 +29,7 @@ <h2 class="text-xl font-bold pt-6 pb-2">Popular Links</h2>
{{range .Clicks}}
<tr class="hover:bg-gray-100 group border-b border-gray-200">
<td class="flex">
<a class="block flex-1 p-2 pr-4 hover:text-blue-500 hover:underline" href="/{{.Short}}">go/{{.Short}}</a>
<a class="block flex-1 p-2 pr-4 hover:text-blue-500 hover:underline" href="/{{.Short}}">{{go}}/{{.Short}}</a>
<a class="flex items-center px-2 invisible group-hover:visible" title="Link Details" href="/.detail/{{.Short}}">
<svg class="hover:fill-blue-500" xmlns="http://www.w3.org/2000/svg" height="1.3em" viewBox="0 0 24 24" width="1.3em" fill="#000000" stroke-width="2"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>
</a>
Expand Down
8 changes: 4 additions & 4 deletions tmpl/opensearch.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>{{.Hostname}}</ShortName>
<ShortName>{{go}}</ShortName>
<Description>Private shortlinks on your tailnet</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16" type="image/png">http://{{.Hostname}}/.static/favicon.png</Image>
<Url type="text/html" method="get" template="http://{{.Hostname}}/{searchTerms}"/>
<moz:SearchForm>http://{{.Hostname}}/</moz:SearchForm>
<Image width="16" height="16" type="image/png">http://{{go}}/.static/favicon.png</Image>
<Url type="text/html" method="get" template="http://{{go}}/{searchTerms}"/>
<moz:SearchForm>http://{{go}}/</moz:SearchForm>
</OpenSearchDescription>
2 changes: 1 addition & 1 deletion tmpl/success.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{ define "main" }}
<h2 class="text-xl font-bold pb-2">Success</h2>

<p><a class="text-blue-600 hover:underline" href="/{{.Short}}">go/{{.Short}}</a> has been saved.</p>
<p><a class="text-blue-600 hover:underline" href="/{{.Short}}">{{go}}/{{.Short}}</a> has been saved.</p>
{{ end }}
Loading