Skip to content

Commit d9dfe56

Browse files
committed
Merge with master
2 parents 9972561 + 0cc6de1 commit d9dfe56

16 files changed

+302
-15
lines changed

adoptResponse.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package httpserve
2+
3+
import (
4+
"io"
5+
)
6+
7+
// NewAdoptResponse will return a new adopt response
8+
func NewAdoptResponse() *AdoptResponse {
9+
var t AdoptResponse
10+
return &t
11+
}
12+
13+
// AdoptResponse is a basic adopt response
14+
type AdoptResponse struct {
15+
}
16+
17+
// ContentType returns the content type
18+
func (t *AdoptResponse) ContentType() (contentType string) {
19+
return "text/plain"
20+
}
21+
22+
// StatusCode returns the status code
23+
func (t *AdoptResponse) StatusCode() (code int) {
24+
return 200
25+
}
26+
27+
// WriteTo will write the internal reader to a provided io.Writer
28+
func (t *AdoptResponse) WriteTo(w io.Writer) (n int64, err error) {
29+
return
30+
}

context.go

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package httpserve
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"net/http"
67
"os"
@@ -22,7 +23,10 @@ func newContext(w http.ResponseWriter, r *http.Request, p Params) *Context {
2223

2324
// Context is the request context
2425
type Context struct {
26+
// Internal context storage, used by Context.Get and Context.Put
2527
s Storage
28+
// hooks are a list of hook functions added during the lifespam of the context
29+
hooks []Hook
2630

2731
Writer http.ResponseWriter
2832
Request *http.Request
@@ -47,15 +51,49 @@ func (c *Context) respond(resp Response) {
4751
if resp == nil {
4852
return
4953
}
54+
55+
if c.redirect(resp) {
56+
return
57+
}
58+
59+
// Write content type!
60+
c.Writer.Header().Set("Content-Type", resp.ContentType())
61+
5062
// Write status code to header
5163
c.Writer.WriteHeader(resp.StatusCode())
64+
5265
// Write response to http.ResponseWriter
5366
if _, err := resp.WriteTo(c.Writer); err != nil {
5467
// Write error to stderr
5568
fmt.Fprintf(os.Stderr, "Error writing to http.ResponseWriter: %v\n", err)
5669
}
5770
}
5871

72+
func (c *Context) redirect(resp Response) (ok bool) {
73+
var redirect *RedirectResponse
74+
if redirect, ok = resp.(*RedirectResponse); !ok {
75+
return
76+
}
77+
78+
c.Writer.Header().Add("Location", redirect.url)
79+
c.Writer.WriteHeader(redirect.code)
80+
return
81+
}
82+
83+
func (c *Context) wasAdopted(resp Response) (ok bool) {
84+
if _, ok = resp.(*AdoptResponse); !ok {
85+
return
86+
}
87+
88+
return
89+
}
90+
91+
func (c *Context) processHooks(statusCode int) {
92+
for i := len(c.hooks) - 1; i > -1; i-- {
93+
c.hooks[i](statusCode, c.s)
94+
}
95+
}
96+
5997
// Write will write a byteslice
6098
func (c *Context) Write(bs []byte) (n int, err error) {
6199
return c.Writer.Write(bs)
@@ -68,7 +106,7 @@ func (c *Context) WriteString(str string) (n int, err error) {
68106

69107
// Param will return the associated parameter value with the provided key
70108
func (c *Context) Param(key string) (value string) {
71-
return c.Param(key)
109+
return c.Params.ByName(key)
72110
}
73111

74112
// Get will retrieve a value for a provided key from the Context's internal storage
@@ -77,6 +115,17 @@ func (c *Context) Get(key string) (value string) {
77115
}
78116

79117
// Put will set a value for a provided key into the Context's internal storage
80-
func (c *Context) Put(key string) (value string) {
81-
return c.s[key]
118+
func (c *Context) Put(key, value string) {
119+
c.s[key] = value
120+
}
121+
122+
// BindJSON is a helper function which binds the request body to a provided value to be parsed as JSON
123+
func (c *Context) BindJSON(value interface{}) (err error) {
124+
defer c.Request.Body.Close()
125+
return json.NewDecoder(c.Request.Body).Decode(value)
126+
}
127+
128+
// AddHook will add a hook function to be ran after the context has completed
129+
func (c *Context) AddHook(fn Hook) {
130+
c.hooks = append(c.hooks, fn)
82131
}

group.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,19 @@ func (g *Group) DELETE(route string, hs ...Handler) {
6969
g.r.DELETE(route, newHandler(hs))
7070
}
7171

72+
// OPTIONS will set a OPTIONS endpoint
73+
func (g *Group) OPTIONS(route string, hs ...Handler) {
74+
if g.route != "" {
75+
route = path.Join(g.route, route)
76+
}
77+
78+
if len(g.hs) > 0 {
79+
hs = append(g.hs, hs...)
80+
}
81+
82+
g.r.OPTIONS(route, newHandler(hs))
83+
}
84+
7285
// Group will return a new group
7386
func (g *Group) Group(route string, hs ...Handler) *Group {
7487
if g.route != "" {

htmlResponse.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package httpserve
2+
3+
import (
4+
"bytes"
5+
"io"
6+
)
7+
8+
// NewHTMLResponse will return a new text response
9+
func NewHTMLResponse(code int, body []byte) *HTMLResponse {
10+
var h HTMLResponse
11+
h.code = code
12+
h.r = bytes.NewReader(body)
13+
return &h
14+
}
15+
16+
// HTMLResponse is a basic text response
17+
type HTMLResponse struct {
18+
code int
19+
r io.Reader
20+
}
21+
22+
// ContentType returns the content type
23+
func (h *HTMLResponse) ContentType() (contentType string) {
24+
return "text/html"
25+
}
26+
27+
// StatusCode returns the status code
28+
func (h *HTMLResponse) StatusCode() (code int) {
29+
return h.code
30+
}
31+
32+
// WriteTo will write the internal reader to a provided io.Writer
33+
func (h *HTMLResponse) WriteTo(w io.Writer) (n int64, err error) {
34+
return io.Copy(w, h.r)
35+
}

htmlResponse_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package httpserve
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
)
7+
8+
func TestHTMLResponse(t *testing.T) {
9+
value := "<html><head></head><body><p>hello world<p></body>"
10+
resp := NewHTMLResponse(200, []byte(value))
11+
buf := bytes.NewBuffer(nil)
12+
resp.WriteTo(buf)
13+
14+
if buf.String() != value {
15+
t.Fatalf("invalid value, expected %#v and received %#v", buf.String(), value)
16+
}
17+
}

httpserve.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ import (
1212
"github.com/bradfitz/http2"
1313
)
1414

15-
const (
16-
invalidTLSFmt = "invalid tls certification pair, neither key nor cert can be empty (%s): %#v"
17-
)
18-
1915
var (
2016
// ErrNotInitialized is returned when an action is performed on an uninitialized instance of Serve
2117
ErrNotInitialized = errors.New("cannot perform action on uninitialized Serve")
@@ -60,6 +56,11 @@ func (s *Serve) DELETE(route string, hs ...Handler) {
6056
s.g.DELETE(route, hs...)
6157
}
6258

59+
// OPTIONS will set a OPTIONS endpoint
60+
func (s *Serve) OPTIONS(route string, hs ...Handler) {
61+
s.g.OPTIONS(route, hs...)
62+
}
63+
6364
// Group will return a new group for a given route and handlers
6465
func (s *Serve) Group(route string, hs ...Handler) *Group {
6566
return s.g.Group(route, hs...)
@@ -101,6 +102,8 @@ func (s *Serve) ListenTLSWithConfig(port uint16, certificateDir string, c Config
101102
return
102103
}
103104

105+
cfg.PreferServerCipherSuites = true
106+
cfg.MinVersion = tls.VersionTLS12
104107
cfg.RootCAs = x509.NewCertPool()
105108
cfg.BuildNameToCertificate()
106109
s.s = newHTTPServer(s.g.r, port, c)

httpserve_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"net/http"
66
"testing"
77
"time"
8-
9-
"fmt"
108
)
119

1210
func TestServeText(t *testing.T) {
@@ -35,7 +33,6 @@ func TestServeText(t *testing.T) {
3533
// Listen within a new goroutine
3634
go func() {
3735
if err := serve.Listen(8080); err != nil && err != http.ErrServerClosed {
38-
fmt.Println("Uhh ", err.Error())
3936
t.Fatal(err)
4037
}
4138
}()

jsonResponse.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,15 @@ func (j *JSONResponse) newValue() (value JSONValue, err error) {
3636
value.Data = j.val
3737
return
3838
}
39+
3940
// Switch on associated value's type
4041
switch v := j.val.(type) {
4142
case error:
4243
// Type is a single error value, create new error slice with error as only item
43-
value.Errors = []error{v}
44+
value.Errors.Push(v)
4445
case []error:
4546
// Type is an error slice, set errors as the value
46-
value.Errors = v
47+
value.Errors.Copy(v)
4748
default:
4849
// Invalid error value, return error
4950
err = fmt.Errorf("invalid type for an error response: %#v", v)
@@ -60,6 +61,7 @@ func (j *JSONResponse) WriteTo(w io.Writer) (n int64, err error) {
6061
// Error encountered while initializing responder, return early
6162
return
6263
}
64+
6365
// Initialize a new JSON encoder
6466
enc := json.NewEncoder(w)
6567
// Encode the responder

jsonValue.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ func UnmarshalJSONValue(bs []byte, val interface{}) (err error) {
2727
return
2828
}
2929

30-
return jv.Errors.Err()
30+
if err = jv.Errors.Err(); err != nil {
31+
return
32+
}
33+
34+
return
3135
}
3236

3337
// JSONValue represents a basic JSON value

noContentResponse.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package httpserve
2+
3+
import (
4+
"io"
5+
)
6+
7+
// NewNoContentResponse will return a new text response
8+
func NewNoContentResponse() *NoContentResponse {
9+
var t NoContentResponse
10+
return &t
11+
}
12+
13+
// NoContentResponse is a basic text response
14+
type NoContentResponse struct {
15+
}
16+
17+
// ContentType returns the content type
18+
func (t *NoContentResponse) ContentType() (contentType string) {
19+
return "text/plain"
20+
}
21+
22+
// StatusCode returns the status code
23+
func (t *NoContentResponse) StatusCode() (code int) {
24+
return 204
25+
}
26+
27+
// WriteTo will write the internal reader to a provided io.Writer
28+
func (t *NoContentResponse) WriteTo(w io.Writer) (n int64, err error) {
29+
return
30+
}

0 commit comments

Comments
 (0)