Skip to content

Commit

Permalink
Remove gorilla mux dependency (#15)
Browse files Browse the repository at this point in the history
Also bump version to 0.0.9.

## Why?

We want to minimize dependencies for our SDKs.
  • Loading branch information
bergundy authored Jul 22, 2024
1 parent cd9d6c5 commit bbded3b
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 75 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ go 1.21

require (
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/stretchr/testify v1.8.4
)

Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
Expand Down
2 changes: 1 addition & 1 deletion nexus/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

// Package version.
const version = "v0.0.8"
const version = "v0.0.9"

const (
// Nexus specific headers.
Expand Down
138 changes: 67 additions & 71 deletions nexus/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import (
"net/http"
"net/url"
"strconv"
"strings"
"time"

"github.com/gorilla/mux"
)

// An HandlerStartOperationResult is the return type from the [Handler] StartOperation and [Operation] Start methods. It
Expand Down Expand Up @@ -264,18 +263,7 @@ func (h *baseHTTPHandler) writeFailure(writer http.ResponseWriter, err error) {
}
}

func (h *httpHandler) startOperation(writer http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
service, err := url.PathUnescape(vars["service"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operation, err := url.PathUnescape(vars["operation"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
func (h *httpHandler) startOperation(service, operation string, writer http.ResponseWriter, request *http.Request) {
options := StartOperationOptions{
RequestID: request.Header.Get(headerRequestID),
CallbackURL: request.URL.Query().Get(queryCallbackURL),
Expand Down Expand Up @@ -304,23 +292,7 @@ func (h *httpHandler) startOperation(writer http.ResponseWriter, request *http.R
}
}

func (h *httpHandler) getOperationResult(writer http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
service, err := url.PathUnescape(vars["service"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operation, err := url.PathUnescape(vars["operation"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operationID, err := url.PathUnescape(vars["operation_id"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
func (h *httpHandler) getOperationResult(service, operation, operationID string, writer http.ResponseWriter, request *http.Request) {
options := GetOperationResultOptions{Header: httpHeaderToNexusHeader(request.Header)}

// If both Request-Timeout http header and wait query string are set, the minimum of the Request-Timeout header
Expand Down Expand Up @@ -365,23 +337,7 @@ func (h *httpHandler) getOperationResult(writer http.ResponseWriter, request *ht
h.writeResult(writer, result)
}

func (h *httpHandler) getOperationInfo(writer http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
service, err := url.PathUnescape(vars["service"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operation, err := url.PathUnescape(vars["operation"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operationID, err := url.PathUnescape(vars["operation_id"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
func (h *httpHandler) getOperationInfo(service, operation, operationID string, writer http.ResponseWriter, request *http.Request) {
options := GetOperationInfoOptions{Header: httpHeaderToNexusHeader(request.Header)}

ctx, cancel, ok := h.contextWithTimeoutFromHTTPRequest(writer, request)
Expand All @@ -407,23 +363,7 @@ func (h *httpHandler) getOperationInfo(writer http.ResponseWriter, request *http
}
}

func (h *httpHandler) cancelOperation(writer http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
service, err := url.PathUnescape(vars["service"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operation, err := url.PathUnescape(vars["operation"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operationID, err := url.PathUnescape(vars["operation_id"])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
func (h *httpHandler) cancelOperation(service, operation, operationID string, writer http.ResponseWriter, request *http.Request) {
options := CancelOperationOptions{Header: httpHeaderToNexusHeader(request.Header)}

ctx, cancel, ok := h.contextWithTimeoutFromHTTPRequest(writer, request)
Expand Down Expand Up @@ -488,6 +428,67 @@ type HandlerOptions struct {
Serializer Serializer
}

func (h *httpHandler) handleRequest(writer http.ResponseWriter, request *http.Request) {
parts := strings.Split(request.URL.EscapedPath(), "/")
// First part is empty (due to leading /)
if len(parts) < 3 {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeNotFound, "not found"))
return
}
service, err := url.PathUnescape(parts[1])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
operation, err := url.PathUnescape(parts[2])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
var operationID string
if len(parts) > 3 {
operationID, err = url.PathUnescape(parts[3])
if err != nil {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "failed to parse URL path"))
return
}
}

switch len(parts) {
case 3: // /{service}/{operation}
if request.Method != "POST" {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "invalid request method: expected POST, got %q", request.Method))
return
}
h.startOperation(service, operation, writer, request)
case 4: // /{service}/{operation}/{operation_id}
if request.Method != "GET" {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "invalid request method: expected GET, got %q", request.Method))
return
}
h.getOperationInfo(service, operation, operationID, writer, request)
case 5:
switch parts[4] {
case "result": // /{service}/{operation}/{operation_id}/result
if request.Method != "GET" {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "invalid request method: expected GET, got %q", request.Method))
return
}
h.getOperationResult(service, operation, operationID, writer, request)
case "cancel": // /{service}/{operation}/{operation_id}/cancel
if request.Method != "POST" {
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeBadRequest, "invalid request method: expected POST, got %q", request.Method))
return
}
h.cancelOperation(service, operation, operationID, writer, request)
default:
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeNotFound, "not found"))
}
default:
h.writeFailure(writer, HandlerErrorf(HandlerErrorTypeNotFound, "not found"))
}
}

// NewHTTPHandler constructs an [http.Handler] from given options for handling Nexus service requests.
func NewHTTPHandler(options HandlerOptions) http.Handler {
if options.Logger == nil {
Expand All @@ -506,10 +507,5 @@ func NewHTTPHandler(options HandlerOptions) http.Handler {
options: options,
}

router := mux.NewRouter().UseEncodedPath()
router.HandleFunc("/{service}/{operation}", handler.startOperation).Methods("POST")
router.HandleFunc("/{service}/{operation}/{operation_id}", handler.getOperationInfo).Methods("GET")
router.HandleFunc("/{service}/{operation}/{operation_id}/result", handler.getOperationResult).Methods("GET")
router.HandleFunc("/{service}/{operation}/{operation_id}/cancel", handler.cancelOperation).Methods("POST")
return router
return http.HandlerFunc(handler.handleRequest)
}

0 comments on commit bbded3b

Please sign in to comment.