Fixed: do not require a Content-Length header (#424)

* Fixed: do not require a Content-Length header

Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>

* Make getData private

Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>

---------

Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
This commit is contained in:
Alessandro (Ale) Segala 2023-07-03 10:44:11 -07:00 committed by GitHub
parent effc2f0d3c
commit 4afb8314b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 53 deletions

View File

@ -37,14 +37,16 @@ func (s *Server) AddBindingInvocationHandler(route string, fn common.BindingInvo
s.mux.Handle(route, optionsHandler(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
var content []byte
if r.ContentLength > 0 {
body, err := io.ReadAll(r.Body)
var (
content []byte
err error
)
if r.Body != nil {
content, err = io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
content = body
}
// assuming Dapr doesn't pass multiple values for key

View File

@ -54,14 +54,13 @@ func (s *Server) AddServiceInvocationHandler(route string, fn common.ServiceInvo
ContentType: r.Header.Get("Content-type"),
}
// check for post with no data
if r.ContentLength > 0 {
content, err := io.ReadAll(r.Body)
var err error
if r.Body != nil {
e.Data, err = io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
e.Data = content
}
ctx := r.Context()

View File

@ -67,6 +67,52 @@ type topicEventJSON struct {
PubsubName string `json:"pubsubname"`
}
func (in topicEventJSON) getData() (data any, rawData []byte) {
var (
err error
v any
)
if len(in.Data) > 0 {
rawData = []byte(in.Data)
data = rawData
// We can assume that rawData is valid JSON
// without checking in.DataContentType == "application/json".
if err = json.Unmarshal(rawData, &v); err == nil {
data = v
// Handling of JSON base64 encoded or escaped in a string.
if str, ok := v.(string); ok {
// This is the path that will most likely succeed.
var (
vString any
decoded []byte
)
if err = json.Unmarshal([]byte(str), &vString); err == nil {
data = vString
} else if decoded, err = base64.StdEncoding.DecodeString(str); err == nil {
// Decoded Base64 encoded JSON does not seem to be in the spec
// but it is in existing unit tests so this handles that case.
var vBase64 any
if err = json.Unmarshal(decoded, &vBase64); err == nil {
data = vBase64
}
}
}
}
} else if in.DataBase64 != "" {
rawData, err = base64.StdEncoding.DecodeString(in.DataBase64)
if err == nil {
data = rawData
if in.DataContentType == "application/json" {
if err = json.Unmarshal(rawData, &v); err == nil {
data = v
}
}
}
}
return data, rawData
}
func (s *Server) registerBaseHandler() {
// register subscribe handler
f := func(w http.ResponseWriter, r *http.Request) {
@ -189,14 +235,25 @@ func (s *Server) AddTopicEventHandler(sub *common.Subscription, fn common.TopicE
s.mux.Handle(sub.Route, optionsHandler(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// check for post with no data
if r.ContentLength == 0 {
var (
body []byte
err error
)
if r.Body != nil {
body, err = io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), PubSubHandlerDropStatusCode)
return
}
}
if len(body) == 0 {
http.Error(w, "nil content", PubSubHandlerDropStatusCode)
return
}
// deserialize the event
var in topicEventJSON
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
if err = json.Unmarshal(body, &in); err != nil {
http.Error(w, err.Error(), PubSubHandlerDropStatusCode)
return
}
@ -208,46 +265,7 @@ func (s *Server) AddTopicEventHandler(sub *common.Subscription, fn common.TopicE
in.Topic = sub.Topic
}
var data interface{}
var rawData []byte
if len(in.Data) > 0 {
rawData = []byte(in.Data)
data = rawData
var v interface{}
// We can assume that rawData is valid JSON
// without checking in.DataContentType == "application/json".
if err := json.Unmarshal(rawData, &v); err == nil {
data = v
// Handling of JSON base64 encoded or escaped in a string.
if str, ok := v.(string); ok {
// This is the path that will most likely succeed.
var vString interface{}
if err := json.Unmarshal([]byte(str), &vString); err == nil {
data = vString
} else if decoded, err := base64.StdEncoding.DecodeString(str); err == nil {
// Decoded Base64 encoded JSON does not seem to be in the spec
// but it is in existing unit tests so this handles that case.
var vBase64 interface{}
if err := json.Unmarshal(decoded, &vBase64); err == nil {
data = vBase64
}
}
}
}
} else if in.DataBase64 != "" {
var err error
rawData, err = base64.StdEncoding.DecodeString(in.DataBase64)
if err == nil {
data = rawData
if in.DataContentType == "application/json" {
var v interface{}
if err := json.Unmarshal(rawData, &v); err == nil {
data = v
}
}
}
}
data, rawData := in.getData()
te := common.TopicEvent{
ID: in.ID,
SpecVersion: in.SpecVersion,

View File

@ -25,12 +25,11 @@ import (
"strings"
"testing"
"github.com/dapr/go-sdk/actor/api"
"github.com/dapr/go-sdk/actor/mock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/dapr/go-sdk/actor/api"
"github.com/dapr/go-sdk/actor/mock"
"github.com/dapr/go-sdk/service/common"
"github.com/dapr/go-sdk/service/internal"
)