Skip to content

Commit

Permalink
feat: Implement V2 Ping endpoint and V2 layers
Browse files Browse the repository at this point in the history
fixes: #432

Signed-off-by: Enobong Udoko <[email protected]>
  • Loading branch information
eno-intel committed Aug 4, 2020
1 parent 5d4b522 commit b40105a
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 4 deletions.
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ require (
github.com/diegoholiveira/jsonlogic v1.0.1-0.20200220175622-ab7989be08b9
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/edgexfoundry/go-mod-bootstrap v0.0.37
github.com/edgexfoundry/go-mod-core-contracts v0.1.65
github.com/edgexfoundry/go-mod-messaging v0.1.19
github.com/edgexfoundry/go-mod-registry v0.1.20
github.com/edgexfoundry/go-mod-secrets v0.0.18
github.com/edgexfoundry/go-mod-core-contracts v0.1.66
github.com/edgexfoundry/go-mod-messaging v0.1.21
github.com/edgexfoundry/go-mod-registry v0.1.21
github.com/edgexfoundry/go-mod-secrets v0.0.19
github.com/fxamacker/cbor/v2 v2.2.0
github.com/golang/snappy v0.0.1 // indirect
github.com/gomodule/redigo v2.0.0+incompatible
Expand Down
74 changes: 74 additions & 0 deletions internal/v2/controller/http/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// Copyright (c) 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package http

import (
"encoding/json"
"fmt"
"net/http"

"github.com/edgexfoundry/go-mod-core-contracts/clients"
"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
contractsV2 "github.com/edgexfoundry/go-mod-core-contracts/v2"
"github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/common"
"github.com/google/uuid"
)

// V2Controller controller for V2 REST APIs
type V2Controller struct {
lc logger.LoggingClient
}

// NewV2Controller creates and initializes an V2Controller
func NewV2Controller(lc logger.LoggingClient) *V2Controller {
return &V2Controller{
lc: lc,
}
}

// Ping handles the request to /ping endpoint. Is used to test if the service is working
// It returns a response as specified by the V2 API swagger in openapi/v2
func (v2c *V2Controller) Ping(w http.ResponseWriter, r *http.Request) {
pingResponse := common.NewPingResponse()

v2c.sendResponse(w, contractsV2.ApiPingRoute, pingResponse, uuid.New().String())

}

// sendResponse puts together the response packet for the V2 API
// api is the V2 API path
// item is the object or data that is sent back as part of the response
// correlationID is a unique identifier correlating a request to its associated response
func (v2c *V2Controller) sendResponse(w http.ResponseWriter, api string, item interface{}, correlationID string) {
data, err := json.Marshal(item)
if err != nil {
v2c.lc.Error(fmt.Sprintf("Unable to marshal %s response", api), "error", err.Error(), clients.CorrelationHeader, correlationID)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

_, err = w.Write(data)
if err != nil {
v2c.lc.Error(fmt.Sprintf("Unable to write %s response", api), "error", err.Error(), clients.CorrelationHeader, correlationID)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Header().Set(clients.CorrelationHeader, correlationID)
w.Header().Set(clients.ContentType, clients.ContentTypeJSON)
w.WriteHeader(http.StatusOK)
}
62 changes: 62 additions & 0 deletions internal/v2/controller/http/controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// Copyright (c) 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package http

import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/edgexfoundry/go-mod-core-contracts/clients"
"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
contractsV2 "github.com/edgexfoundry/go-mod-core-contracts/v2"
"github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestPingRquest(t *testing.T) {
target := NewV2Controller(logger.NewMockClient())

req, err := http.NewRequest(http.MethodGet, contractsV2.ApiPingRoute, nil)
if err != nil {
t.Fatal(err)
}

recorder := httptest.NewRecorder()
handler := http.HandlerFunc(target.Ping)

handler.ServeHTTP(recorder, req)

require.Equal(t, http.StatusOK, recorder.Code)

assert.Equal(t, clients.ContentTypeJSON, recorder.HeaderMap.Get(clients.ContentType))
assert.NotEmpty(t, recorder.HeaderMap.Get(clients.CorrelationHeader))

require.NotEmpty(t, recorder.Body.String())

actual := common.PingResponse{}
err = json.Unmarshal(recorder.Body.Bytes(), &actual)
require.NoError(t, err)

_, err = time.Parse(time.UnixDate, actual.Timestamp)
assert.NoError(t, err)

require.Equal(t, contractsV2.ApiVersion, actual.Versionable.ApiVersion)
}
27 changes: 27 additions & 0 deletions internal/v2/routes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package v2

import (
"net/http"

v2http "github.com/edgexfoundry/app-functions-sdk-go/internal/v2/controller/http"
"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
contractsV2 "github.com/edgexfoundry/go-mod-core-contracts/v2"
"github.com/gorilla/mux"
)

// ConfigureStandardRoutes loads default V2 routes
func ConfigureStandardRoutes(router *mux.Router, lc logger.LoggingClient) {
controller := v2http.NewV2Controller(lc)

router.HandleFunc(contractsV2.ApiPingRoute, controller.Ping).Methods(http.MethodGet)
}
4 changes: 4 additions & 0 deletions internal/webserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/edgexfoundry/app-functions-sdk-go/internal/common"
"github.com/edgexfoundry/app-functions-sdk-go/internal/security"
"github.com/edgexfoundry/app-functions-sdk-go/internal/telemetry"
v2 "github.com/edgexfoundry/app-functions-sdk-go/internal/v2"
"github.com/edgexfoundry/go-mod-core-contracts/clients"
"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"

Expand Down Expand Up @@ -293,6 +294,9 @@ func (webserver *WebServer) ConfigureStandardRoutes() {

// Secrets
webserver.router.HandleFunc(internal.SecretsAPIRoute, webserver.secretHandler).Methods(http.MethodPost)

// V2 API routes
v2.ConfigureStandardRoutes(webserver.router, webserver.LoggingClient)
}

// SetupTriggerRoute adds a route to handle trigger pipeline from HTTP request
Expand Down

0 comments on commit b40105a

Please sign in to comment.