Matthew Holt
6 years ago
6 changed files with 161 additions and 30 deletions
@ -1,28 +1,18 @@ |
|||||
package main |
package main |
||||
|
|
||||
import ( |
import ( |
||||
"log" |
caddycmd "bitbucket.org/lightcodelabs/caddy2/cmd" |
||||
|
|
||||
_ "net/http/pprof" |
|
||||
|
|
||||
"bitbucket.org/lightcodelabs/caddy2" |
|
||||
|
|
||||
// this is where modules get plugged in
|
// this is where modules get plugged in
|
||||
|
|
||||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp" |
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp" |
||||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/caddylog" |
_ "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/staticfiles" |
||||
|
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/staticresp" |
||||
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddytls" |
_ "bitbucket.org/lightcodelabs/caddy2/modules/caddytls" |
||||
_ "bitbucket.org/lightcodelabs/dynamicconfig" |
|
||||
_ "bitbucket.org/lightcodelabs/proxy" |
|
||||
) |
) |
||||
|
|
||||
func main() { |
func main() { |
||||
err := caddy2.StartAdmin("127.0.0.1:1234") |
caddycmd.Main() |
||||
if err != nil { |
|
||||
log.Fatal(err) |
|
||||
} |
|
||||
defer caddy2.StopAdmin() |
|
||||
|
|
||||
select {} |
|
||||
} |
} |
||||
|
@ -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