-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add Content-Type middleware (#21)
* feat: Add mapping between api.Item and item.Item * feat: Add MediaType middleware function * refactor: Nest library code in libs folder * fix: Empty content type should also return error * fix: Linting issues
- Loading branch information
1 parent
7d9eb4d
commit 3763605
Showing
17 changed files
with
431 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package api | ||
|
||
import ( | ||
"github.com/glass-cms/glasscms/item" | ||
"github.com/glass-cms/glasscms/parser" | ||
) | ||
|
||
// MapToDomain converts an api.Item to an item.Item. | ||
func (i *Item) MapToDomain() *item.Item { | ||
if i == nil { | ||
return nil | ||
} | ||
return &item.Item{ | ||
UID: i.Id, | ||
Name: i.Name, | ||
Path: i.Path, | ||
Content: i.Content, | ||
Hash: parser.HashContent([]byte(i.Content)), | ||
CreateTime: i.CreateTime, | ||
UpdateTime: i.UpdateTime, | ||
Properties: i.Properties, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package api_test | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/glass-cms/glasscms/api" | ||
"github.com/glass-cms/glasscms/item" | ||
"github.com/glass-cms/glasscms/parser" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestItem_MapToDomain(t *testing.T) { | ||
t.Parallel() | ||
|
||
type fields struct { | ||
Content string | ||
CreateTime time.Time | ||
DisplayName string | ||
ID string | ||
Name string | ||
Path string | ||
Properties map[string]interface{} | ||
UpdateTime time.Time | ||
} | ||
|
||
tests := []struct { | ||
name string | ||
fields fields | ||
want *item.Item | ||
}{ | ||
{ | ||
name: "Complete Item Mapping", | ||
fields: fields{ | ||
Content: "Test Content", | ||
CreateTime: time.Now().Add(-24 * time.Hour), | ||
DisplayName: "Test Display Name", | ||
ID: "1234", | ||
Name: "Test Name", | ||
Path: "/test/path", | ||
Properties: map[string]interface{}{"key1": "value1", "key2": "value2"}, | ||
UpdateTime: time.Now(), | ||
}, | ||
want: &item.Item{ | ||
UID: "1234", | ||
Name: "Test Name", | ||
Path: "/test/path", | ||
Content: "Test Content", | ||
Hash: parser.HashContent([]byte("Test Content")), | ||
CreateTime: time.Now().Add(-24 * time.Hour), | ||
UpdateTime: time.Now(), | ||
Properties: map[string]any{"key1": "value1", "key2": "value2"}, | ||
}, | ||
}, | ||
{ | ||
name: "Empty Item Mapping", | ||
fields: fields{ | ||
Content: "", | ||
CreateTime: time.Time{}, | ||
DisplayName: "", | ||
ID: "", | ||
Name: "", | ||
Path: "", | ||
Properties: nil, | ||
UpdateTime: time.Time{}, | ||
}, | ||
want: &item.Item{ | ||
UID: "", | ||
Name: "", | ||
Path: "", | ||
Content: "", | ||
Hash: parser.HashContent([]byte("")), | ||
CreateTime: time.Time{}, | ||
UpdateTime: time.Time{}, | ||
Properties: nil, | ||
}, | ||
}, | ||
{ | ||
name: "Nil Properties Mapping", | ||
fields: fields{ | ||
Content: "Test Content", | ||
CreateTime: time.Now().Add(-24 * time.Hour), | ||
DisplayName: "Test Display Name", | ||
ID: "5678", | ||
Name: "Test Name 2", | ||
Path: "/test/path2", | ||
Properties: nil, | ||
UpdateTime: time.Now(), | ||
}, | ||
want: &item.Item{ | ||
UID: "5678", | ||
Name: "Test Name 2", | ||
Path: "/test/path2", | ||
Content: "Test Content", | ||
Hash: parser.HashContent([]byte("Test Content")), | ||
CreateTime: time.Now().Add(-24 * time.Hour), | ||
UpdateTime: time.Now(), | ||
Properties: nil, | ||
}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
apiItem := &api.Item{ | ||
Content: tt.fields.Content, | ||
CreateTime: tt.fields.CreateTime, | ||
DisplayName: tt.fields.DisplayName, | ||
Id: tt.fields.ID, | ||
Name: tt.fields.Name, | ||
Path: tt.fields.Path, | ||
Properties: tt.fields.Properties, | ||
UpdateTime: tt.fields.UpdateTime, | ||
} | ||
got := apiItem.MapToDomain() | ||
|
||
// Adjust for potential differences in time (e.g., slight differences due to test execution timing) | ||
if !got.CreateTime.IsZero() && !tt.want.CreateTime.IsZero() { | ||
got.CreateTime = tt.want.CreateTime | ||
} | ||
if !got.UpdateTime.IsZero() && !tt.want.UpdateTime.IsZero() { | ||
got.UpdateTime = tt.want.UpdateTime | ||
} | ||
|
||
assert.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
output: './out' | ||
database: | ||
dsn: ':memory:' | ||
dsn: 'file:test.db?cache=shared&mode=memory' | ||
driver: 'sqlite3' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## Libs | ||
|
||
The libs folder contains modules and files that are auxiliary to the application. Libraries contain utility functions that are non-specific to the application domain. They are used to encapsulate code that is used in multiple places in the application. The libs folder is not a place for domain-specific code. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package ctx | ||
package context | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package mediatype | ||
|
||
const ( | ||
// ApplicationJSON json mime type. | ||
ApplicationJSON string = "application/json" | ||
// ApplicationXML xml mime type. | ||
ApplicationXML string = "application/xml" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Package mediatype provides types, constant and parsing functions for media types (MIME). | ||
package mediatype | ||
|
||
import ( | ||
"mime" | ||
"strings" | ||
) | ||
|
||
// MediaType represents a media type (MIME). | ||
// | ||
// A MIME type most commonly consists of just two parts: a type and a subtype, | ||
// separated by a slash (/) — with no whitespace between:. | ||
type MediaType struct { | ||
MediaType string | ||
|
||
Type string | ||
Subtype *string | ||
|
||
// Parameters are optional key-value pairs that follow the type/subtype in a MIME type. | ||
Parameters map[string]string | ||
} | ||
|
||
// Parse parses a media type string and returns a MediaType. | ||
// If the string is not a valid media type, an error is returned. | ||
func Parse(s string) (*MediaType, error) { | ||
mt, params, err := mime.ParseMediaType(s) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
split := strings.Split(mt, "/") | ||
var subtype *string | ||
|
||
// If there is a subtype, set it. | ||
if len(split) == 2 { | ||
subtype = &split[1] | ||
} | ||
|
||
return &MediaType{ | ||
MediaType: mt, | ||
Type: split[0], | ||
Subtype: subtype, | ||
Parameters: params, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Package mediatype provides types, constant and parsing functions for media types (MIME). | ||
package mediatype_test | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/glass-cms/glasscms/lib/mediatype" | ||
) | ||
|
||
func stringPtr(s string) *string { | ||
return &s | ||
} | ||
|
||
func TestParse(t *testing.T) { | ||
t.Parallel() | ||
|
||
tests := []struct { | ||
name string | ||
input string | ||
want *mediatype.MediaType | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "application/json", | ||
input: "application/json", | ||
want: &mediatype.MediaType{ | ||
MediaType: "application/json", | ||
Type: "application", | ||
Subtype: stringPtr("json"), | ||
Parameters: map[string]string{}, | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "application/json with charset", | ||
input: "application/json; charset=utf-8", | ||
want: &mediatype.MediaType{ | ||
MediaType: "application/json", | ||
Type: "application", | ||
Subtype: stringPtr("json"), | ||
Parameters: map[string]string{"charset": "utf-8"}, | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "without subtype", | ||
input: "text", | ||
want: &mediatype.MediaType{ | ||
MediaType: "text", | ||
Type: "text", | ||
Subtype: nil, | ||
Parameters: map[string]string{}, | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "invalid media type with slash", | ||
input: "text/", | ||
want: nil, | ||
wantErr: true, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
got, err := mediatype.Parse(tt.input) | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
} | ||
|
||
if !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("Parse() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.