# Name

_template_ - use Go templates to reply

# Description

The _template_ handler allows you to dynamically respond to queries by just writing a Go template. The
template is a file that is watched and reloaded when it changes. The template is the string version of a message
is generated by `codeberg.org/miekg/dns`, i.e.:

```txt
;; QUERY, rcode: NOERROR, id: 49123, flags: qr rd ra

;; QUESTION SECTION:
miek.nl.                IN      MX

;; ANSWER SECTION:
miek.nl.        11381   IN      MX      10 aspmx2.googlemail.com.
miek.nl.        11381   IN      MX      10 aspmx3.googlemail.com.
miek.nl.        11381   IN      MX      5 alt1.aspmx.l.google.com.
miek.nl.        11381   IN      MX      5 alt2.aspmx.l.google.com.
miek.nl.        11381   IN      MX      1 aspmx.l.google.com.
```

This is a _valid_ template and will be parsed by _template_ into a message and returned to the client.
However, for one thing, the query ID will not be correct, so that line should become:

```txt
;; QUERY, rcode: NOERROR, id: {{.ID}}, flags: qr rd ra
```

When nothing is matched _template_ will call the next handler, see below for more details.

# Syntax

```
template REGEX [TYPE]... {
    TEMPLATE
}
```

- **REGEX** will be matched against the incoming question name. Expressions larger than a 1000 charactes
  return an error during setup.
- **TYPE** is the type to be matched, if not given all types are matched.
- **TEMPLATE** is that template file that should be parsed and executed. If that the path is relative the
  global `root` path is prepended.

# Templates

A template must return a complete message that can be parsed back into an actual DNS message. The template
parsing is _not_ case insensitive, i.e. `answer section:` will not be parsed but `ANSWER SECTION:` is.

Each template gets the following variables (see the godoc of Data):

- `.Zone` the matched zone string (e.g. `example.org.`), from the context.
- `.ID` the query ID.
- `.Name` the query name.
- `.Class` the query class.
- `.Type` the query type.
- `.Question` the matched question RR.
- `.Msg` the complete message.
- `.ResponseWriter` that holds all the data that can be extracted from the response writer.

And the following functions (all functions start with a capital letter):

- `Ctx(key string)` return the value for the key from the current context. This allows extracting any data
  other handlers have added to the context, such as the _geoip_ handler does, i.e. with `Ctx("geoip/city")`.

# Examples

## Resolve to NXDOMAIN

```conffile
example.org. {
    template .* {
      nxdomain.go.tmpl
    }
}
```

Where `nxdomain.go.tmpl` contains:

```txt
;; QUERY, rcode: NOERROR, id: {{.ID}}, flags: qr rd ra

;; QUESTION SECTION:
{{.Question}}

;; AUTHORITY SECTION:
{{.Zone}}   IN SOA ns.icann.org. noc.dns.icann.org. 2025082229 7200 3600 1209600 3600
{{if Ctx "geoip/asn"}}
{{.Zone}}   IN TXT "{{Ctx "geoip/asn"}}"
{{end}}
```

# Also see

[Go regexp](https://golang.org/pkg/regexp/) for details about the regex implementation and
[Go template](https://golang.org/pkg/text/template/) for the template language reference. And atomdns-geoip(7)
for documentation on what elements are added to the context.

# Bugs

The template is parsed on every query, which is a bit excessive. See <https://codeberg.org/miekg/dns/issues/319>.
