Skip to content

Commit

Permalink
Merge pull request #16 from trco/support-images
Browse files Browse the repository at this point in the history
Support "image/..." content types in responses
  • Loading branch information
trco authored Sep 15, 2024
2 parents 52c9fb8 + 6bc0963 commit 60cc6be
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 15 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ To use records created through the Wannabe API with an HTTPS scheme in the reque

**Which request and response body content types are currently supported?**

Wannabe currently supports the following content types: *application/json*, *application/xml*, *text/xml*, *text/plain*, and *text/html*.
Wannabe explicitly supports the following content types in requests and responses: *application/json*, *application/xml*, *text/xml*, *text/plain*, and *text/html*. Additionally, it is tested to support *image/...* content types in responses and other content types where the response body consists of binary data.

**Which request and response body content encodings are currently supported?**

Expand Down
15 changes: 9 additions & 6 deletions internal/handler/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package handler

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -142,34 +143,36 @@ func setResponse(encodedRecord []byte, request *http.Request) (*http.Response, e

func encodeBody(decodedBody interface{}, contentTypeHeader []string, contentEncodingHeader []string) ([]byte, error) {
var body []byte
var err error

contentType := record.GetContentType(contentTypeHeader)
switch {
case contentType == "application/json":
var err error
body, err = json.Marshal(decodedBody)
if err != nil {
return nil, fmt.Errorf("SetResponse: failed marshaling body: %v", err)
return nil, fmt.Errorf("failed marshaling application/json body: %v", err)
}
case contentType == "application/xml", contentType == "text/xml":
var err error
mapValue := mxj.Map(decodedBody.(map[string]interface{}))
body, err = mapValue.Xml()
if err != nil {
return body, fmt.Errorf("Generate: failed unmarshaling XML body: %v", err)
return body, fmt.Errorf("failed unmarshaling application/xml or text/xml body: %v", err)
}
case contentType == "text/plain", contentType == "text/html":
body = []byte(decodedBody.(string))
default:
return nil, fmt.Errorf("SetResponse: unsupported content type: %s", contentTypeHeader)
body, err = base64.StdEncoding.DecodeString(decodedBody.(string))
if err != nil {
return body, fmt.Errorf("failed unmarshaling body: %v", err)
}
}

// gzip the body that was unzipped before storing it to the record
contentEncoding := record.GetContentEncoding(contentEncodingHeader)
if contentEncoding == "gzip" {
compressedBody, err := record.Gzip(body)
if err != nil {
return nil, fmt.Errorf("SetResponse: failed compressing response body: %s", err)
return nil, fmt.Errorf("failed compressing response body: %s", err)
}

return compressedBody, nil
Expand Down
4 changes: 2 additions & 2 deletions internal/handler/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,11 @@ func TestEncodeBody(t *testing.T) {
wantErr: false,
},
{
name: "unsupported content type",
name: "random content type",
decodedBody: "unsupported",
contentType: []string{"unsupported"},
contentEncoding: []string{},
want: nil,
want: []byte{186, 123, 46, 166, 154, 43},
wantErr: true,
},
{
Expand Down
7 changes: 4 additions & 3 deletions internal/record/decode_body.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

func DecodeBody(encodedBody []byte, contentEncodingHeader []string, contentTypeHeader []string) (interface{}, error) {
var body interface{}
var err error

if len(encodedBody) == 0 {
return body, nil
Expand All @@ -22,7 +23,7 @@ func DecodeBody(encodedBody []byte, contentEncodingHeader []string, contentTypeH

// gunzip the body before decoding it to the interface
if contentEncoding == "gzip" {
var err error

encodedBody, err = Gunzip(encodedBody)
if err != nil {
return nil, fmt.Errorf("DecodeBody: failed unzipping body: %v", err)
Expand All @@ -33,7 +34,7 @@ func DecodeBody(encodedBody []byte, contentEncodingHeader []string, contentTypeH

switch {
case contentType == "application/json":
err := json.Unmarshal(encodedBody, &body)
err = json.Unmarshal(encodedBody, &body)
if err != nil {
return nil, fmt.Errorf("DecodeBody: failed unmarshaling JSON body: %v", err)
}
Expand All @@ -46,7 +47,7 @@ func DecodeBody(encodedBody []byte, contentEncodingHeader []string, contentTypeH
case contentType == "text/plain", contentType == "text/html":
body = string(encodedBody)
default:
return nil, fmt.Errorf("DecodeBody: unsupported content type: %s", contentType)
body = encodedBody
}

return body, nil
Expand Down
6 changes: 3 additions & 3 deletions internal/record/decode_body_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestDecodeBody(t *testing.T) {
encodedBody: []byte(`{"key": "value"}`),
contentType: []string{},
contentEncoding: []string{},
want: nil,
want: []byte{123, 34, 107, 101, 121, 34, 58, 32, 34, 118, 97, 108, 117, 101, 34, 125},
},
{
name: "json content type",
Expand Down Expand Up @@ -58,11 +58,11 @@ func TestDecodeBody(t *testing.T) {
want: "\u003c!DOCTYPE html\u003e\n \u003chtml\u003e\n \u003ch1\u003eHerman Melville - Moby-Dick\u003c/h1\u003e\n \u003c/html\u003e",
},
{
name: "unsupported content type",
name: "random content type",
encodedBody: []byte(`{"key": "value"}`),
contentType: []string{"unsupported/type"},
contentEncoding: []string{},
want: nil,
want: []byte{123, 34, 107, 101, 121, 34, 58, 32, 34, 118, 97, 108, 117, 101, 34, 125},
},
{
name: "json content type, gzip content encoding",
Expand Down

0 comments on commit 60cc6be

Please sign in to comment.