Skip to content

Commit

Permalink
Refactor for V1 flow supporting AWS Json
Browse files Browse the repository at this point in the history
  • Loading branch information
dhumphreys01 committed Jan 17, 2024
1 parent 39895d4 commit 7893a9a
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 8 deletions.
71 changes: 68 additions & 3 deletions app/gosqs/gosqs.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"strings"
"time"

"github.com/Admiral-Piett/goaws/app/utils"

log "github.com/sirupsen/logrus"

"github.com/Admiral-Piett/goaws/app"
Expand Down Expand Up @@ -116,11 +118,13 @@ func ListQueues(w http.ResponseWriter, req *http.Request) {
}

type CreateQueueRequest struct {
QueueName string `json: QueueName`
Attributes map[string]string `json: Attributes`
Tags map[string]string `json: Tags`
QueueName string `json:"QueueName" schema:"QueueName"`
Attributes Attributes `json:"Attributes" schema:"Attributes"`
Tags map[string]string `json:"Tags" schema:"Tags"`
}

// TODO - populate for all possible SQS attributes
// TODO - copy for SNS
type Attributes map[string]string

func parseCreateQueueRequestBody(w http.ResponseWriter, req *http.Request) (bool, CreateQueueRequest) {
Expand All @@ -146,6 +150,58 @@ func parseCreateQueueRequestBody(w http.ResponseWriter, req *http.Request) (bool
return byJson, *requestBody
}

func CreateQueueV1(req *http.Request) (int, interface{}) {
requestBody := &CreateQueueRequest{}
ok := utils.TransformRequest(requestBody, req)
if !ok {
log.Error("Invalid Type Requested - CreateQueueV1")
return http.StatusInternalServerError, nil
}
queueName := requestBody.QueueName

queueUrl := "http://" + app.CurrentEnvironment.Host + ":" + app.CurrentEnvironment.Port +
"/" + app.CurrentEnvironment.AccountID + "/" + queueName
if app.CurrentEnvironment.Region != "" {
queueUrl = "http://" + app.CurrentEnvironment.Region + "." + app.CurrentEnvironment.Host + ":" +
app.CurrentEnvironment.Port + "/" + app.CurrentEnvironment.AccountID + "/" + queueName
}
queueArn := "arn:aws:sqs:" + app.CurrentEnvironment.Region + ":" + app.CurrentEnvironment.AccountID + ":" + queueName

if _, ok := app.SyncQueues.Queues[queueName]; !ok {
log.Println("Creating Queue:", queueName)
queue := &app.Queue{
Name: queueName,
URL: queueUrl,
Arn: queueArn,
TimeoutSecs: app.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout,
ReceiveWaitTimeSecs: app.CurrentEnvironment.QueueAttributeDefaults.ReceiveMessageWaitTimeSeconds,
MaximumMessageSize: app.CurrentEnvironment.QueueAttributeDefaults.MaximumMessageSize,
IsFIFO: app.HasFIFOQueueName(queueName),
EnableDuplicates: app.CurrentEnvironment.EnableDuplicates,
Duplicates: make(map[string]time.Time),
}
if err := validateAndSetQueueAttributesJson(queue, requestBody.Attributes); err != nil {
return createErrorResponseV1(err)
}
// FIXME - remove this once sure
//if byJson {
// if err := validateAndSetQueueAttributesJson(queue, requestBody.Attributes); err != nil {
// return createErrorResponseV1(err)
// }
//} else {
// if err := validateAndSetQueueAttributes(queue, req.Form); err != nil {
// return createErrorResponseV1(err)
// }
//}
app.SyncQueues.Lock()
app.SyncQueues.Queues[queueName] = queue
app.SyncQueues.Unlock()
}

respStruct := app.CreateQueueResponse{"http://queue.amazonaws.com/doc/2012-11-05/", app.CreateQueueResult{QueueUrl: queueUrl}, app.ResponseMetadata{RequestId: "00000000-0000-0000-0000-000000000000"}}
return http.StatusOK, respStruct
}

func CreateQueue(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/xml")
byJson, requestBody := parseCreateQueueRequestBody(w, req)
Expand Down Expand Up @@ -1048,3 +1104,12 @@ func createErrorResponse(w http.ResponseWriter, req *http.Request, err string) {
log.Printf("error: %v\n", err)
}
}

func createErrorResponseV1(err error) (int, app.ErrorResponse) {
er := app.SqsErrors[err.Error()]
respStruct := app.ErrorResponse{
Result: app.ErrorResult{Type: er.Type, Code: er.Code, Message: er.Message},
RequestId: "00000000-0000-0000-0000-000000000000",
}
return er.HttpError, respStruct
}
27 changes: 25 additions & 2 deletions app/router/router.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package router

import (
"encoding/xml"
"io"
"net/http"
"strings"
Expand Down Expand Up @@ -28,10 +29,25 @@ func New() http.Handler {
return r
}

func encodeResponse(w http.ResponseWriter, statusCode int, body interface{}) {
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(statusCode)
// TODO - replace with gorilla/schema
enc := xml.NewEncoder(w)
enc.Indent(" ", " ")
if err := enc.Encode(body); err != nil {
log.Printf("error: %v\n", err)
}
}

var routingTableV1 = map[string]func(r *http.Request) (int, interface{}){
"CreateQueue": sqs.CreateQueueV1,
}

var routingTable = map[string]http.HandlerFunc{
// SQS
"ListQueues": sqs.ListQueues,
"CreateQueue": sqs.CreateQueue,
"ListQueues": sqs.ListQueues,
//"CreateQueue": sqs.CreateQueue,
"GetQueueAttributes": sqs.GetQueueAttributes,
"SetQueueAttributes": sqs.SetQueueAttributes,
"SendMessage": sqs.SendMessage,
Expand Down Expand Up @@ -72,6 +88,13 @@ func actionHandler(w http.ResponseWriter, req *http.Request) {
"action": action,
"url": req.URL,
}).Debug("Handling URL request")
// If we don't find a match in this table, pass on to the existing flow.
jsonFn, ok := routingTableV1[action]
if ok {
statusCode, responseBody := jsonFn(req)
encodeResponse(w, statusCode, responseBody)
return
}
fn, ok := routingTable[action]
if !ok {
log.Println("Bad Request - Action:", action)
Expand Down
49 changes: 49 additions & 0 deletions app/utils/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package utils

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

log "github.com/sirupsen/logrus"

"github.com/gorilla/schema"
)

var xmlDecoder = schema.NewDecoder()

// QUESTION - alternately we could have the router.actionHandler method call this, but then our router maps
// need to track the request type AND the function call. I think there'd be a lot of interface switching
// back and forth.
func TransformRequest(resultingStruct interface{}, req *http.Request) (success bool) {
// TODO - put this somewhere else so we don't keep on rehashing this?
xmlDecoder.IgnoreUnknownKeys(true)
// TODO - do I still need the byJSON?
// Should remove this flag after validateAndSetQueueAttributes was updated
//byJson := false

switch req.Header.Get("Content-Type") {
case "application/x-amz-json-1.0":
//Read body data to parse json
decoder := json.NewDecoder(req.Body)
err := decoder.Decode(resultingStruct)
if err != nil {
log.Debugf("TransformRequest Failure - %s", err.Error())
return false
}
//byJson = true
default:
// TODO - parse XML
err := req.ParseForm()
if err != nil {
log.Debugf("TransformRequest Failure - %s", err.Error())
return false
}
err = xmlDecoder.Decode(resultingStruct, req.PostForm)
if err != nil {
log.Debugf("TransformRequest Failure - %s", err.Error())
return false
}
}

return true
}
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gorilla/schema v1.2.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand All @@ -22,7 +23,7 @@ require (
)

retract (
v1.1.0
v1.1.1
v1.1.2
v1.1.2
v1.1.1
v1.1.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/schema v1.2.1 h1:tjDxcmdb+siIqkTNoV+qRH2mjYdr2hHe5MKXbp61ziM=
github.com/gorilla/schema v1.2.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
Expand Down

0 comments on commit 7893a9a

Please sign in to comment.