Matthew Holt
6 years ago
6 changed files with 161 additions and 30 deletions
@ -1,28 +1,18 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"log" |
|||
|
|||
_ "net/http/pprof" |
|||
|
|||
"bitbucket.org/lightcodelabs/caddy2" |
|||
caddycmd "bitbucket.org/lightcodelabs/caddy2/cmd" |
|||
|
|||
// this is where modules get plugged in
|
|||
|
|||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp" |
|||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/caddylog" |
|||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/reverseproxy" |
|||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/staticfiles" |
|||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/staticresp" |
|||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddytls" |
|||
_ "bitbucket.org/lightcodelabs/dynamicconfig" |
|||
_ "bitbucket.org/lightcodelabs/proxy" |
|||
) |
|||
|
|||
func main() { |
|||
err := caddy2.StartAdmin("127.0.0.1:1234") |
|||
if err != nil { |
|||
log.Fatal(err) |
|||
} |
|||
defer caddy2.StopAdmin() |
|||
|
|||
select {} |
|||
caddycmd.Main() |
|||
} |
|||
|
@ -0,0 +1,75 @@ |
|||
package caddyhttp |
|||
|
|||
import ( |
|||
"net/http" |
|||
"strings" |
|||
) |
|||
|
|||
type Replacer struct { |
|||
req *http.Request |
|||
resp http.ResponseWriter |
|||
custom map[string]string |
|||
} |
|||
|
|||
// Map sets a custom variable mapping to a value.
|
|||
func (r *Replacer) Map(variable, value string) { |
|||
r.custom[variable] = value |
|||
} |
|||
|
|||
// Replace replaces placeholders in input with the value. If
|
|||
// the value is empty string, the placeholder is substituted
|
|||
// with the value empty.
|
|||
func (r *Replacer) Replace(input, empty string) string { |
|||
if !strings.Contains(input, phOpen) { |
|||
return input |
|||
} |
|||
|
|||
input = r.replaceAll(input, empty, r.defaults()) |
|||
input = r.replaceAll(input, empty, r.custom) |
|||
|
|||
return input |
|||
} |
|||
|
|||
func (r *Replacer) replaceAll(input, empty string, mapping map[string]string) string { |
|||
for key, val := range mapping { |
|||
if val == "" { |
|||
val = empty |
|||
} |
|||
input = strings.ReplaceAll(input, phOpen+key+phClose, val) |
|||
} |
|||
return input |
|||
} |
|||
|
|||
func (r *Replacer) defaults() map[string]string { |
|||
m := map[string]string{ |
|||
"host": r.req.Host, |
|||
"method": r.req.Method, |
|||
"scheme": func() string { |
|||
if r.req.TLS != nil { |
|||
return "https" |
|||
} |
|||
return "http" |
|||
}(), |
|||
"uri": r.req.URL.RequestURI(), |
|||
} |
|||
|
|||
for field, vals := range r.req.Header { |
|||
m[">"+strings.ToLower(field)] = strings.Join(vals, ",") |
|||
} |
|||
|
|||
for field, vals := range r.resp.Header() { |
|||
m["<"+strings.ToLower(field)] = strings.Join(vals, ",") |
|||
} |
|||
|
|||
for _, cookie := range r.req.Cookies() { |
|||
m["~"+cookie.Name] = cookie.Value |
|||
} |
|||
|
|||
for param, vals := range r.req.URL.Query() { |
|||
m["?"+param] = strings.Join(vals, ",") |
|||
} |
|||
|
|||
return m |
|||
} |
|||
|
|||
const phOpen, phClose = "{", "}" |
@ -0,0 +1,57 @@ |
|||
package staticresp |
|||
|
|||
import ( |
|||
"fmt" |
|||
"net/http" |
|||
|
|||
"bitbucket.org/lightcodelabs/caddy2" |
|||
"bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp" |
|||
) |
|||
|
|||
func init() { |
|||
caddy2.RegisterModule(caddy2.Module{ |
|||
Name: "http.responders.static", |
|||
New: func() (interface{}, error) { return new(Static), nil }, |
|||
}) |
|||
} |
|||
|
|||
// Static implements a simple responder for static responses.
|
|||
type Static struct { |
|||
StatusCode int `json:"status_code"` |
|||
Headers map[string][]string `json:"headers"` |
|||
Body string `json:"body"` |
|||
Close bool `json:"close"` |
|||
} |
|||
|
|||
func (s Static) ServeHTTP(w http.ResponseWriter, r *http.Request) error { |
|||
repl := r.Context().Value(caddyhttp.ReplacerCtxKey).(*caddyhttp.Replacer) |
|||
|
|||
// close the connection
|
|||
r.Close = s.Close |
|||
|
|||
// set all headers, with replacements
|
|||
for field, vals := range s.Headers { |
|||
field = repl.Replace(field, "") |
|||
for i := range vals { |
|||
vals[i] = repl.Replace(vals[i], "") |
|||
} |
|||
w.Header()[field] = vals |
|||
} |
|||
|
|||
// write the headers with a status code
|
|||
statusCode := s.StatusCode |
|||
if statusCode == 0 { |
|||
statusCode = http.StatusOK |
|||
} |
|||
w.WriteHeader(statusCode) |
|||
|
|||
// write the response body, with replacements
|
|||
if s.Body != "" { |
|||
fmt.Fprint(w, repl.Replace(s.Body, "")) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
// Interface guard
|
|||
var _ caddyhttp.Handler = (*Static)(nil) |
Loading…
Reference in new issue