Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
// response.
type Empty struct{}

// DefaultEncoding contains the mime type of the default encoding to fall
// back on if no `Accept` or `Content-Type` header was provided.
// DefaultEncoding contains the media type of the default encoding to fall back
// on if no `Accept` or `Content-Type` header was provided.
var DefaultEncoding = "text/plain"

type Middleware func(fasthttp.RequestHandler) fasthttp.RequestHandler
Expand Down
22 changes: 10 additions & 12 deletions decode.go → encoding/decode.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package don
package encoding

import (
"context"
Expand All @@ -16,33 +16,31 @@ type DecoderConstraint interface {
Unmarshaler | ContextUnmarshaler | RequestParser
}

// RegisterDecoder registers a request decoder.
func RegisterDecoder[T DecoderConstraint](contentType string, dec T, aliases ...string) {
// RegisterDecoder registers a request decoder for a given media type.
func RegisterDecoder[T DecoderConstraint](dec T, mime string, aliases ...string) {
switch d := any(dec).(type) {
case Unmarshaler:
decoders[contentType] = func(ctx *fasthttp.RequestCtx, v any) error {
decoders[mime] = func(ctx *fasthttp.RequestCtx, v any) error {
return d(ctx.Request.Body(), v)
}

case ContextUnmarshaler:
decoders[contentType] = func(ctx *fasthttp.RequestCtx, v any) error {
decoders[mime] = func(ctx *fasthttp.RequestCtx, v any) error {
return d(ctx, ctx.Request.Body(), v)
}

case RequestParser:
decoders[contentType] = d
decoders[mime] = d
}

for _, alias := range aliases {
decoders[alias] = decoders[contentType]
decoders[alias] = decoders[mime]
}
}

func getDecoder(mime string) (RequestParser, error) {
if enc := decoders[mime]; enc != nil {
return enc, nil
}
return nil, ErrUnsupportedMediaType
// GetDecoder returns the request decoder for a given media type.
func GetDecoder(mime string) RequestParser {
return decoders[mime]
}

var decoders = map[string]RequestParser{}
18 changes: 9 additions & 9 deletions decode_test.go → encoding/decode_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package don_test
package encoding_test

import (
"context"
"io"
"reflect"
"testing"

"github.com/abemedia/go-don"
"github.com/abemedia/go-don/encoding"
"github.com/abemedia/go-don/pkg/httptest"
"github.com/valyala/fasthttp"
)
Expand Down Expand Up @@ -44,29 +44,29 @@ func TestRegisterDecoder(t *testing.T) {
})
}

func testRegisterDecoder[T don.DecoderConstraint](t *testing.T, dec T, contentType, alias string) {
func testRegisterDecoder[T encoding.DecoderConstraint](t *testing.T, dec T, contentType, alias string) {
t.Helper()

don.RegisterDecoder(contentType, dec, alias)
encoding.RegisterDecoder(dec, contentType, alias)

for _, v := range []string{contentType, alias} {
decode, err := don.GetDecoder(v)
if err != nil {
t.Error(err)
decode := encoding.GetDecoder(v)
if decode == nil {
t.Error("decoder not found")
continue
}

req := httptest.NewRequest("", "", v, nil)

var b []byte
if err = decode(req, &b); err != nil {
if err := decode(req, &b); err != nil {
t.Error(err)
} else if string(b) != v {
t.Error("should decode request")
}

req.Request.SetBody(nil)
if err = decode(req, &b); err == nil {
if err := decode(req, &b); err == nil {
t.Error("should return error")
}
}
Expand Down
22 changes: 10 additions & 12 deletions encode.go → encoding/encode.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package don
package encoding

import (
"context"
Expand All @@ -16,11 +16,11 @@ type EncoderConstraint interface {
Marshaler | ContextMarshaler | ResponseEncoder
}

// RegisterEncoder registers a response encoder.
func RegisterEncoder[T EncoderConstraint](contentType string, enc T, aliases ...string) {
// RegisterEncoder registers a response encoder on a given media type.
func RegisterEncoder[T EncoderConstraint](enc T, mime string, aliases ...string) {
switch e := any(enc).(type) {
case Marshaler:
encoders[contentType] = func(ctx *fasthttp.RequestCtx, v any) error {
encoders[mime] = func(ctx *fasthttp.RequestCtx, v any) error {
b, err := e(v)
if err != nil {
return err
Expand All @@ -30,7 +30,7 @@ func RegisterEncoder[T EncoderConstraint](contentType string, enc T, aliases ...
}

case ContextMarshaler:
encoders[contentType] = func(ctx *fasthttp.RequestCtx, v any) error {
encoders[mime] = func(ctx *fasthttp.RequestCtx, v any) error {
b, err := e(ctx, v)
if err != nil {
return err
Expand All @@ -40,19 +40,17 @@ func RegisterEncoder[T EncoderConstraint](contentType string, enc T, aliases ...
}

case ResponseEncoder:
encoders[contentType] = e
encoders[mime] = e
}

for _, alias := range aliases {
encoders[alias] = encoders[contentType]
encoders[alias] = encoders[mime]
}
}

func getEncoder(mime string) (ResponseEncoder, error) {
if enc := encoders[mime]; enc != nil {
return enc, nil
}
return nil, ErrNotAcceptable
// GetEncoder returns the response encoder for a given media type.
func GetEncoder(mime string) ResponseEncoder {
return encoders[mime]
}

var encoders = map[string]ResponseEncoder{}
18 changes: 9 additions & 9 deletions encode_test.go → encoding/encode_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package don_test
package encoding_test

import (
"context"
"io"
"testing"

"github.com/abemedia/go-don"
"github.com/abemedia/go-don/encoding"
"github.com/abemedia/go-don/pkg/httptest"
"github.com/valyala/fasthttp"
)
Expand Down Expand Up @@ -43,27 +43,27 @@ func TestRegisterEncoder(t *testing.T) {
})
}

func testRegisterEncoder[T don.EncoderConstraint](t *testing.T, dec T, contentType, alias string) {
func testRegisterEncoder[T encoding.EncoderConstraint](t *testing.T, dec T, contentType, alias string) {
t.Helper()

don.RegisterEncoder(contentType, dec, alias)
encoding.RegisterEncoder(dec, contentType, alias)

for _, v := range []string{contentType, alias} {
encode, err := don.GetEncoder(v)
if err != nil {
t.Error(err)
encode := encoding.GetEncoder(v)
if encode == nil {
t.Error("encoder not found")
continue
}

req := httptest.NewRequest("", "", v, nil)

if err = encode(req, []byte(v)); err != nil {
if err := encode(req, []byte(v)); err != nil {
t.Error(err)
} else if string(req.Response.Body()) != v {
t.Error("should encode response")
}

if err = encode(req, []byte{}); err == nil {
if err := encode(req, []byte{}); err == nil {
t.Error("should return error")
}
}
Expand Down
6 changes: 3 additions & 3 deletions encoding/form/form.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package form

import (
"github.com/abemedia/go-don"
"github.com/abemedia/go-don/decoder"
"github.com/abemedia/go-don/encoding"
"github.com/valyala/fasthttp"
)

Expand All @@ -22,6 +22,6 @@ func decodeMultipartForm(ctx *fasthttp.RequestCtx, v any) error {
}

func init() {
don.RegisterDecoder("application/x-www-form-urlencoded", decodeForm)
don.RegisterDecoder("multipart/form-data", decodeMultipartForm)
encoding.RegisterDecoder(decodeForm, "application/x-www-form-urlencoded")
encoding.RegisterDecoder(decodeMultipartForm, "multipart/form-data")
}
4 changes: 2 additions & 2 deletions encoding/form/form_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ func TestForm(t *testing.T) {
}

t.Run("URLEncoded", func(t *testing.T) {
test.Decode(t, test.EncodingTest[item]{
test.Decode(t, test.EncodingOptions[item]{
Mime: "application/x-www-form-urlencoded",
Raw: "foo=bar",
Parsed: item{Foo: "bar"},
})
})

t.Run("Multipart", func(t *testing.T) {
test.Decode(t, test.EncodingTest[item]{
test.Decode(t, test.EncodingOptions[item]{
Mime: `multipart/form-data;boundary="boundary"`,
Raw: "--boundary\nContent-Disposition: form-data; name=\"foo\"\n\nbar\n--boundary\n",
Parsed: item{Foo: "bar"},
Expand Down
6 changes: 3 additions & 3 deletions encoding/json/json.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package json

import (
"github.com/abemedia/go-don"
"github.com/abemedia/go-don/encoding"
"github.com/goccy/go-json"
"github.com/valyala/fasthttp"
)
Expand All @@ -15,6 +15,6 @@ func encodeJSON(ctx *fasthttp.RequestCtx, v any) error {
}

func init() {
don.RegisterDecoder("application/json", decodeJSON)
don.RegisterEncoder("application/json", encodeJSON)
encoding.RegisterDecoder(decodeJSON, "application/json")
encoding.RegisterEncoder(encodeJSON, "application/json")
}
2 changes: 1 addition & 1 deletion encoding/json/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestJSON(t *testing.T) {
Foo string `json:"foo"`
}

test.Encoding(t, test.EncodingTest[item]{
test.Encoding(t, test.EncodingOptions[item]{
Mime: "application/json",
Raw: `{"foo":"bar"}` + "\n",
Parsed: item{Foo: "bar"},
Expand Down
6 changes: 3 additions & 3 deletions encoding/msgpack/msgpack.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package msgpack

import (
"github.com/abemedia/go-don"
"github.com/abemedia/go-don/encoding"
"github.com/valyala/fasthttp"
"github.com/vmihailenco/msgpack/v5"
)
Expand All @@ -15,6 +15,6 @@ func encodeMsgpack(ctx *fasthttp.RequestCtx, v any) error {
}

func init() {
don.RegisterDecoder("application/x-msgpack", decodeMsgpack)
don.RegisterEncoder("application/x-msgpack", encodeMsgpack)
encoding.RegisterDecoder(decodeMsgpack, "application/x-msgpack")
encoding.RegisterEncoder(encodeMsgpack, "application/x-msgpack")
}
2 changes: 1 addition & 1 deletion encoding/msgpack/msgpack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestMsgpack(t *testing.T) {
Foo string `msgpack:"foo"`
}

test.Encoding(t, test.EncodingTest[item]{
test.Encoding(t, test.EncodingOptions[item]{
Mime: "application/x-msgpack",
Raw: "\x81\xa3foo\xa3bar",
Parsed: item{Foo: "bar"},
Expand Down
9 changes: 5 additions & 4 deletions encoding/text/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package text

import (
"bytes"
"encoding"
stdencoding "encoding"
"reflect"
"strconv"
"sync"

"github.com/abemedia/go-don"
"github.com/abemedia/go-don/encoding"
"github.com/abemedia/go-don/internal/byteconv"
"github.com/valyala/fasthttp"
)
Expand Down Expand Up @@ -102,7 +103,7 @@ func newUnmarshaler(typ reflect.Type) (func([]byte, reflect.Value) error, error)
if isPtr && v.IsNil() {
v.Set(reflect.New(typ))
}
return v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b) //nolint:forcetypeassert
return v.Interface().(stdencoding.TextUnmarshaler).UnmarshalText(b) //nolint:forcetypeassert
}, nil
}

Expand All @@ -126,9 +127,9 @@ func newUnmarshaler(typ reflect.Type) (func([]byte, reflect.Value) error, error)
//nolint:gochecknoglobals
var (
unmarshalers sync.Map
unmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*stdencoding.TextUnmarshaler)(nil)).Elem()
)

func init() {
don.RegisterDecoder("text/plain", decode)
encoding.RegisterDecoder(decode, "text/plain")
}
7 changes: 4 additions & 3 deletions encoding/text/encode.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package text

import (
"encoding"
stdencoding "encoding"
"fmt"
"strconv"

"github.com/abemedia/go-don"
"github.com/abemedia/go-don/encoding"
"github.com/abemedia/go-don/internal/byteconv"
"github.com/valyala/fasthttp"
)
Expand Down Expand Up @@ -49,7 +50,7 @@ func encode(ctx *fasthttp.RequestCtx, v any) error {
b = strconv.AppendFloat(ctx.Response.Body(), v, 'f', -1, 64)
case bool:
b = strconv.AppendBool(ctx.Response.Body(), v)
case encoding.TextMarshaler:
case stdencoding.TextMarshaler:
b, err = v.MarshalText()
case error:
b = byteconv.Atob(v.Error())
Expand All @@ -68,5 +69,5 @@ func encode(ctx *fasthttp.RequestCtx, v any) error {
}

func init() {
don.RegisterEncoder("text/plain", encode)
encoding.RegisterEncoder(encode, "text/plain")
}
6 changes: 3 additions & 3 deletions encoding/xml/xml.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package xml
import (
"encoding/xml"

"github.com/abemedia/go-don"
"github.com/abemedia/go-don/encoding"
"github.com/valyala/fasthttp"
)

Expand All @@ -16,6 +16,6 @@ func encodeXML(ctx *fasthttp.RequestCtx, v any) error {
}

func init() {
don.RegisterDecoder("application/xml", decodeXML, "text/xml")
don.RegisterEncoder("application/xml", encodeXML, "text/xml")
encoding.RegisterDecoder(decodeXML, "application/xml", "text/xml")
encoding.RegisterEncoder(encodeXML, "application/xml", "text/xml")
}
2 changes: 1 addition & 1 deletion encoding/xml/xml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestXML(t *testing.T) {
Foo string `xml:"foo"`
}

test.Encoding(t, test.EncodingTest[item]{
test.Encoding(t, test.EncodingOptions[item]{
Mime: "application/xml",
Raw: "<item><foo>bar</foo></item>",
Parsed: item{Foo: "bar"},
Expand Down
Loading