From 1267c7acee9a4f270e1ed914ef1fcb57e89a5b51 Mon Sep 17 00:00:00 2001 From: Eric Marden Date: Fri, 10 Mar 2017 18:43:56 -0600 Subject: [PATCH] generates automatic Media Types for an endpoint - a vendor media type is automatically generated from the `API.Name`, `Endponter.GetName()`, and `Endpointer.GetVersion()` values fixes #21 --- glide.lock | 8 +++++--- glide.yaml | 1 + hyperdrive.go | 17 +++++++++++++++++ hyperdrive_test.go | 8 ++++++-- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/glide.lock b/glide.lock index 954ed8d..5838b09 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 7bf3b501233a2729c72609562a733518952e95ed73780b2bb20d56c2e7b60d89 -updated: 2017-03-10T17:45:56.469489343-06:00 +hash: 74a8b2717375531d919d594c0868c2490810ffb111600bb28124e4880e9164c5 +updated: 2017-03-10T18:37:33.280466765-06:00 imports: - name: github.com/caarlos0/env version: d0de832ed2fbc4e7bfaa30ab5cf0b3417d15f529 @@ -11,9 +11,11 @@ imports: version: 392c28fe23e1c45ddba891b0320b3b5df220beea - name: github.com/Masterminds/semver version: 59c29afe1a994eacb71c833025ca7acf874bb1da +- name: github.com/metal3d/go-slugify + version: 7ac2014b2f23e254684c08d597496681d12c6a8a testImports: - name: github.com/davecgh/go-spew - version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew - name: github.com/pmezard/go-difflib diff --git a/glide.yaml b/glide.yaml index 03aad8e..5087833 100644 --- a/glide.yaml +++ b/glide.yaml @@ -8,6 +8,7 @@ import: version: ^2.1.0 - package: github.com/Masterminds/semver version: 1.2.2 +- package: github.com/metal3d/go-slugify testImport: - package: github.com/stretchr/testify version: ^1.1.4 diff --git a/hyperdrive.go b/hyperdrive.go index d52a44e..ae009da 100644 --- a/hyperdrive.go +++ b/hyperdrive.go @@ -1,11 +1,14 @@ package hyperdrive import ( + "fmt" "log" "net/http" + "strings" "time" "github.com/gorilla/mux" + slugify "github.com/metal3d/go-slugify" ) // API is a logical collection of one or more endpoints, connecting requests @@ -47,9 +50,23 @@ func (api *API) AddEndpoint(e Endpointer) { api.Router.Handle(e.GetPath(), api.DefaultMiddlewareChain(NewMethodHandler(e))) } +// GetMediaType returns a media type string, sans any content-type extension (e.g. json), +// based on the name of the API, the Endpoint, and the Endpoint's version. The Media Type +// produced will be used for Content Negotiation, via the Accept header, as well as routing +// to the appropriate endpoint, when the media type appears in the request headers (e.g. +// Accept and Content-Type). It will also be used, after content negotation in the +// Content-Type response header. +func (api *API) GetMediaType(e Endpointer) string { + return fmt.Sprintf("application/vnd.%s.%s.%s", slug(api.Name), slug(e.GetName()), e.GetVersion()) +} + // Start starts the configured http server, listening on the configured Port // (default: 5000). Set the PORT environment variable to change this. func (api *API) Start() { log.Printf("Hyperdrive API starting on PORT %d in ENVIRONMENT %s", api.conf.Port, api.conf.Env) log.Fatal(api.Server.ListenAndServe()) } + +func slug(s string) string { + return strings.ToLower(slugify.Marshal(s)) +} diff --git a/hyperdrive_test.go b/hyperdrive_test.go index 8c56553..066f550 100644 --- a/hyperdrive_test.go +++ b/hyperdrive_test.go @@ -18,12 +18,12 @@ type HyperdriveTestSuite struct { } func (suite *HyperdriveTestSuite) SetupTest() { - suite.TestAPI = NewAPI("Test API", "Test API Desc") + suite.TestAPI = NewAPI("API", "Test API Desc") suite.TestEndpoint = NewEndpoint("Test", "Test Endpoint", "/test", "1.0.1") suite.TestHandler = NewMethodHandler(suite.TestEndpoint) suite.TestRoot = NewRootResource(suite.TestAPI) suite.TestEndpointRepresentation = Representation{"name": "Test", "desc": "Test Endpoint", "path": "/test", "methods": []string{"OPTIONS"}} - suite.TestRootRepresentation = Representation{"resource": "api", "name": "Test API", "endpoints": []Representation{suite.TestEndpointRepresentation}} + suite.TestRootRepresentation = Representation{"resource": "api", "name": "API", "endpoints": []Representation{suite.TestEndpointRepresentation}} } func (suite *HyperdriveTestSuite) TestNewAPI() { @@ -34,6 +34,10 @@ func (suite *HyperdriveTestSuite) TestAPIServer() { suite.IsType(&http.Server{}, suite.TestAPI.Server, "expects an instance of *http.Server") } +func (suite *HyperdriveTestSuite) TestGetMediaType() { + suite.Equal("application/vnd.api.test.v1.0.1", suite.TestAPI.GetMediaType(suite.TestEndpoint), "returns a media type string") +} + func TestHyperdriveTestSuite(t *testing.T) { suite.Run(t, new(HyperdriveTestSuite)) }