summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclsr <clsr@clsr.net>2017-09-01 16:11:42 +0200
committerclsr <clsr@clsr.net>2017-09-01 16:11:42 +0200
commit7e1f90f27d876db67158ca4787420ec30c18f86b (patch)
tree4526e5924c926af4814968a49c2dd7875fdf0dd0
parentee431f1e85a8ee7d3c6e069c8858c671da1c2acd (diff)
downloadcnp-go-7e1f90f27d876db67158ca4787420ec30c18f86b.tar.gz
cnp-go-7e1f90f27d876db67158ca4787420ec30c18f86b.zip
Distinguish between response length=0 and no length parameter
Response.Length returns -1 when the parameter is not present and 0 when it's set to 0. Response.SetLength will only unset the parameter when given -1.
-rw-r--r--common.go4
-rw-r--r--message.go44
-rw-r--r--message_test.go2
-rw-r--r--request.go20
-rw-r--r--response.go20
-rw-r--r--server.go2
6 files changed, 67 insertions, 25 deletions
diff --git a/common.go b/common.go
index 310da86..2d73189 100644
--- a/common.go
+++ b/common.go
@@ -30,10 +30,10 @@ func readLimitedLine(br *bufio.Reader, length int) ([]byte, error) {
}
}
-func getInt(m *Message, param string) (int64, error) {
+func getInt(m *Message, param string, fallback int64) (int64, error) {
p := m.Param(param)
if p == "" {
- return 0, nil
+ return fallback, nil
}
n, err := strconv.ParseUint(p, 10, 63)
if err != nil || (n != 0 && p[0] == '0') || (n == 0 && len(p) != 1) {
diff --git a/message.go b/message.go
index fdb16b3..ccd455f 100644
--- a/message.go
+++ b/message.go
@@ -114,22 +114,14 @@ func (msg *Message) TryComputeLength() bool {
return true
}
-// SetLength sets the length header parameter to n.
-func (msg *Message) SetLength(n int64) {
- if n == 0 {
- msg.SetParam("length", "")
- } else {
- setInt(msg, "length", n)
- }
+// Intent retrieves the message header intent.
+func (msg *Message) Intent() string {
+ return msg.Header.Intent
}
-// Length gets the length header parameter (or 0 if it's not set or invalid).
-func (msg *Message) Length() int64 {
- n, err := getInt(msg, "length")
- if err != nil {
- return 0
- }
- return n
+// SetIntent sets the message header intent.
+func (msg *Message) SetIntent(s string) {
+ msg.Header.Intent = s
}
// Param retrieves a header parameter. It performs no value validation.
@@ -147,19 +139,29 @@ func (msg *Message) SetParam(key, value string) {
}
}
-// Intent retrieves the message header intent.
-func (msg *Message) Intent() string {
- return msg.Header.Intent
+// Length gets the length header parameter (or 0 if it's not set or invalid).
+func (msg *Message) Length() int64 {
+ n, err := getInt(msg, "length", 0)
+ if err != nil {
+ return 0
+ }
+ return n
}
-// SetIntent sets the message header intent.
-func (msg *Message) SetIntent(s string) {
- msg.Header.Intent = s
+// SetLength sets the length header parameter to n.
+//
+// If negative or zero, the parameter is unset.
+func (msg *Message) SetLength(n int64) {
+ if n <= 0 {
+ msg.SetParam("length", "")
+ } else {
+ setInt(msg, "length", n)
+ }
}
// Validate validates the message header parameter value format (length).
func (msg *Message) Validate() error {
- _, err := getInt(msg, "length")
+ _, err := getInt(msg, "length", 0)
return err
}
diff --git a/message_test.go b/message_test.go
index 6955fc3..1a73fa5 100644
--- a/message_test.go
+++ b/message_test.go
@@ -92,7 +92,7 @@ func TestParse(t *testing.T) {
}
} else if !msgEqual(msg, tst.m) {
t.Errorf("\nexpected: %+v\ngot: %+v", tst.m, msg)
- } else if l := msg.Length(); tst.v == nil && l != int64(len(tst.b)) {
+ } else if l := msg.Length(); tst.v == nil && (l != int64(len(tst.b)) && !(l < 0 == (len(tst.b) == 0))) {
t.Errorf("%+v: expected length %d, got %d", tst.m, len(tst.b), l)
} else if err = msg.Validate(); !errorEqual(err, tst.v) {
t.Errorf("%+v: expected validation error %+v, got %+v (%s)", msg, tst.v, err, err)
diff --git a/request.go b/request.go
index 0fb27a2..44bae56 100644
--- a/request.go
+++ b/request.go
@@ -219,6 +219,26 @@ func (r *Request) SetSelect(selector, query string) error {
return setSelect(&r.Message, "select", selector, query)
}
+// Length gets the length request parameter (or 0 if not set or invalid).
+func (r *Request) Length() int64 {
+ n, err := getInt(&r.Message, "length", 0)
+ if err != nil {
+ return 0
+ }
+ return n
+}
+
+// SetLength sets the length request parameter to n.
+//
+// If n is negative or zero, the parameter is unset.
+func (r *Request) SetLength(n int64) {
+ if n <= 0 {
+ r.SetParam("length", "")
+ } else {
+ setInt(&r.Message, "length", n)
+ }
+}
+
// Validate validates the request header intent and parameter value format
// (length, name, type, if_modified, select)
func (r *Request) Validate() error {
diff --git a/response.go b/response.go
index 3ecb961..4c3f753 100644
--- a/response.go
+++ b/response.go
@@ -224,6 +224,26 @@ func (r *Response) SetSelect(selector, query string) error {
return setSelect(&r.Message, "select", selector, query)
}
+// Length gets the length response parameter (or -1 if it's not set or invalid).
+func (r *Response) Length() int64 {
+ n, err := getInt(&r.Message, "length", -1)
+ if err != nil {
+ return -1
+ }
+ return n
+}
+
+// SetLength sets the length response parameter to n.
+//
+// If negative, the parameter is unset.
+func (r *Response) SetLength(n int64) {
+ if n < 0 {
+ r.SetParam("length", "")
+ } else {
+ setInt(&r.Message, "length", n)
+ }
+}
+
// Validate validates the response intent and header parameter value format
// (length, name, type, time, modified, location, reason, select)
func (r *Response) Validate() error {
diff --git a/server.go b/server.go
index 26301ab..c8491fc 100644
--- a/server.go
+++ b/server.go
@@ -139,7 +139,7 @@ func (srv *Server) HandleConn(conn net.Conn) {
req.Body = io.LimitReader(req.Body, req.Length())
if srv.Validate {
- if err != nil {
+ if err := req.Validate(); err != nil {
panic(err)
}
}