From 16834d64def4a4d21122fdcab725d047d073738c Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Sun, 15 Oct 2023 20:58:46 -0400 Subject: [PATCH] templates: Clarify `include` args docs, add `.ClientIP` (#5898) --- modules/caddyhttp/templates/templates.go | 53 ++++++++++++++--------- modules/caddyhttp/templates/tplcontext.go | 14 +++++- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/modules/caddyhttp/templates/templates.go b/modules/caddyhttp/templates/templates.go index 65359d9e9..4da02b580 100644 --- a/modules/caddyhttp/templates/templates.go +++ b/modules/caddyhttp/templates/templates.go @@ -46,7 +46,8 @@ func init() { // // ##### `.Args` // -// A slice of arguments passed to this page/context, for example as the result of a `include`. +// A slice of arguments passed to this page/context, for example +// as the result of a [`include`](#include). // // ``` // {{index .Args 0}} // first argument @@ -103,8 +104,8 @@ func init() { // Reads and returns the contents of another file, and parses it // as a template, adding any template definitions to the template // stack. If there are no definitions, the filepath will be the -// definition name. Any {{ define }} blocks will be accessible by -// {{ template }} or {{ block }}. Imports must happen before the +// definition name. Any `{{ define }}` blocks will be accessible by +// `{{ template }}` or `{{ block }}`. Imports must happen before the // template or block action is called. Note that the contents are // NOT escaped, so you should only import trusted template files. // @@ -125,12 +126,13 @@ func init() { // // Includes the contents of another file, rendering it in-place. // Optionally can pass key-value pairs as arguments to be accessed -// by the included file. Note that the contents are NOT escaped, -// so you should only include trusted template files. +// by the included file. Use [`.Args N`](#args) to access the N-th +// argument, 0-indexed. Note that the contents are NOT escaped, so +// you should only include trusted template files. // // ``` // {{include "path/to/file.html"}} // no arguments -// {{include "path/to/file.html" "arg1" 2 "value 3"}} // with arguments +// {{include "path/to/file.html" "arg0" 1 "value 2"}} // with arguments // ``` // // ##### `readFile` @@ -145,7 +147,8 @@ func init() { // // ##### `listFiles` // -// Returns a list of the files in the given directory, which is relative to the template context's file root. +// Returns a list of the files in the given directory, which is relative +// to the template context's file root. // // ``` // {{listFiles "/mydir"}} @@ -165,12 +168,21 @@ func init() { // // ##### `.RemoteIP` // -// Returns the client's IP address. +// Returns the connection's IP address. // // ``` // {{.RemoteIP}} // ``` // +// ##### `.ClientIP` +// +// Returns the real client's IP address, if `trusted_proxies` was configured, +// otherwise returns the connection's IP address. +// +// ``` +// {{.ClientIP}} +// ``` +// // ##### `.Req` // // Accesses the current HTTP request, which has various fields, including: @@ -186,7 +198,8 @@ func init() { // // ##### `.OriginalReq` // -// Like .Req, except it accesses the original HTTP request before rewrites or other internal modifications. +// Like [`.Req`](#req), except it accesses the original HTTP +// request before rewrites or other internal modifications. // // ##### `.RespHeader.Add` // @@ -222,11 +235,13 @@ func init() { // // ##### `splitFrontMatter` // -// Splits front matter out from the body. Front matter is metadata that appears at the very beginning of a file or string. Front matter can be in YAML, TOML, or JSON formats: +// Splits front matter out from the body. Front matter is metadata that +// appears at the very beginning of a file or string. Front matter can +// be in YAML, TOML, or JSON formats: // // **TOML** front matter starts and ends with `+++`: // -// ``` +// ```toml // +++ // template = "blog" // title = "Blog Homepage" @@ -236,7 +251,7 @@ func init() { // // **YAML** is surrounded by `---`: // -// ``` +// ```yaml // --- // template: blog // title: Blog Homepage @@ -246,14 +261,12 @@ func init() { // // **JSON** is simply `{` and `}`: // -// ``` -// -// { -// "template": "blog", -// "title": "Blog Homepage", -// "sitename": "A Caddy site" -// } -// +// ```json +// { +// "template": "blog", +// "title": "Blog Homepage", +// "sitename": "A Caddy site" +// } // ``` // // The resulting front matter will be made available like so: diff --git a/modules/caddyhttp/templates/tplcontext.go b/modules/caddyhttp/templates/tplcontext.go index a7d531482..63e645d37 100644 --- a/modules/caddyhttp/templates/tplcontext.go +++ b/modules/caddyhttp/templates/tplcontext.go @@ -265,7 +265,7 @@ func (c TemplateContext) Cookie(name string) string { return "" } -// RemoteIP gets the IP address of the client making the request. +// RemoteIP gets the IP address of the connection's remote IP. func (c TemplateContext) RemoteIP() string { ip, _, err := net.SplitHostPort(c.Req.RemoteAddr) if err != nil { @@ -274,6 +274,18 @@ func (c TemplateContext) RemoteIP() string { return ip } +// ClientIP gets the IP address of the real client making the request +// if the request is trusted (see trusted_proxies), otherwise returns +// the connection's remote IP. +func (c TemplateContext) ClientIP() string { + address := caddyhttp.GetVar(c.Req.Context(), caddyhttp.ClientIPVarKey).(string) + clientIP, _, err := net.SplitHostPort(address) + if err != nil { + clientIP = address // no port + } + return clientIP +} + // Host returns the hostname portion of the Host header // from the HTTP request. func (c TemplateContext) Host() (string, error) {