Skip to content

Commit

Permalink
Opt to generate specs from structs
Browse files Browse the repository at this point in the history
  • Loading branch information
joecorall committed Apr 25, 2024
1 parent d9949b7 commit 04ed5a3
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 328 deletions.
109 changes: 0 additions & 109 deletions client.yml

This file was deleted.

6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ module github.com/lehigh-university-libraries/scyllaridae
go 1.21.3

require gopkg.in/yaml.v3 v3.0.1

require (
github.com/kr/pretty v0.3.1 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
15 changes: 14 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
56 changes: 56 additions & 0 deletions internal/config/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package config

// ServerConfig defines server-specific configurations.
//
// swagger:model ServerConfig
type ServerConfig struct {
// Label of the server configuration used for identification.
//
// required: true
Label string `yaml:"label"`

// HTTP method used for sending data to the destination server.
//
// required: true
DestinationHTTPMethod string `yaml:"destinationHttpMethod"`

// Header name for the file resource.
//
// required: false
FileHeader string `yaml:"fileHeader,omitempty"`

// Header name for additional arguments passed to the command.
//
// required: false
ArgHeader string `yaml:"argHeader,omitempty"`

// Indicates whether the authentication header should be forwarded.
//
// required: false
ForwardAuth bool `yaml:"forwardAuth,omitempty"`

// List of MIME types allowed for processing.
//
// required: true
AllowedMimeTypes []string `yaml:"allowedMimeTypes"`

// Commands and arguments ran by MIME type.
//
// required: true
CmdByMimeType map[string]Command `yaml:"cmdByMimeType"`
}

// Command describes the command and arguments to execute for a specific MIME type.
//
// swagger:model Command
type Command struct {
// Command to execute.
//
// required: true
Cmd string `yaml:"cmd"`

// Arguments for the command.
//
// required: false
Args []string `yaml:"args"`
}
97 changes: 16 additions & 81 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,21 @@ package main

import (
"bytes"
"encoding/json"
"fmt"
"log/slog"
"net/http"
"os"
"os/exec"
"strings"

scyllaridae "github.com/lehigh-university-libraries/scyllaridae/internal/config"
"github.com/lehigh-university-libraries/scyllaridae/pkg/api"

"gopkg.in/yaml.v3"
)

type Data struct {
Actor Actor `json:"actor"`
Object Object `json:"object"`
Attachment Attachment `json:"attachment"`
Type string `json:"type"`
Summary string `json:"summary"`
}

type Actor struct {
Id string `json:"id"`
}

type Object struct {
Id string `json:"id"`
URL []URL `json:"url"`
NewVersion bool `json:"isNewVersion"`
}

type URL struct {
Name string `json:"name"`
Type string `json:"type"`
Href string `json:"href"`
MediaType string `json:"mediaType"`
Rel string `json:"rel"`
}

type Attachment struct {
Type string `json:"type"`
Content Content `json:"content"`
MediaType string `json:"mediaType"`
}

type Content struct {
MimeType string `json:"mimetype"`
Args string `json:"args"`
SourceUri string `json:"source_uri"`
DestinationUri string `json:"destination_uri"`
FileUploadUri string `json:"file_upload_uri"`
WebServiceUri string
}

type Cmd struct {
Command string `yaml:"cmd,omitempty"`
Args []string `yaml:"args,omitempty"`
}

type Config struct {
Label string `yaml:"label"`
Method string `yaml:"destination-http-method"`
FileHeader string `yaml:"file-header"`
ArgHeader string `yaml:"arg-header"`
ForwardAuth bool `yaml:"forward-auth"`
AllowedMimeTypes []string `yaml:"allowed-mimetypes"`
CmdByMimeType map[string]Cmd `yaml:"cmd-by-mimetype"`
}

var (
config *Config
config *scyllaridae.ServerConfig
)

func init() {
Expand Down Expand Up @@ -105,15 +51,15 @@ func MessageHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

// Read the Alpaca message payload
message, err := DecodeAlpacaMessage(r)
message, err := api.DecodeAlpacaMessage(r)
if err != nil {
slog.Error("Error decoding Pub/Sub message", "err", err)
http.Error(w, "Error decoding Pub/Sub message", http.StatusInternalServerError)
return
}

// Fetch the file contents from the URL
sourceResp, err := http.Get(message.Attachment.Content.SourceUri)
sourceResp, err := http.Get(message.Attachment.Content.SourceURI)
if err != nil {
slog.Error("Error fetching source file contents", "err", err)
http.Error(w, "Error fetching file contents from URL", http.StatusInternalServerError)
Expand Down Expand Up @@ -144,7 +90,7 @@ func MessageHandler(w http.ResponseWriter, r *http.Request) {
}

// Create the PUT request
req, err := http.NewRequest(config.Method, message.Attachment.Content.DestinationUri, &outBuf)
req, err := http.NewRequest(config.DestinationHTTPMethod, message.Attachment.Content.DestinationURI, &outBuf)
if err != nil {
slog.Error("Error creating HTTP request", "err", err)
http.Error(w, "Error creating HTTP request", http.StatusInternalServerError)
Expand All @@ -155,21 +101,21 @@ func MessageHandler(w http.ResponseWriter, r *http.Request) {
req.Header.Set("Authorization", auth)
}
req.Header.Set("Content-Type", message.Attachment.Content.MimeType)
req.Header.Set("Content-Location", message.Attachment.Content.FileUploadUri)
req.Header.Set("Content-Location", message.Attachment.Content.FileUploadURI)

// Execute the PUT request
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
slog.Error("Error sending request", "method", config.Method, "err", err)
slog.Error("Error sending request", "method", config.DestinationHTTPMethod, "err", err)
http.Error(w, "Internal error.", http.StatusInternalServerError)
return
}
defer resp.Body.Close()

if resp.StatusCode > 299 {
slog.Error("Request failed on destination server", "code", resp.StatusCode)
http.Error(w, fmt.Sprintf("%s request failed with status code %d", config.Method, resp.StatusCode), resp.StatusCode)
http.Error(w, fmt.Sprintf("%s request failed with status code %d", config.DestinationHTTPMethod, resp.StatusCode), resp.StatusCode)
return
}

Expand All @@ -180,17 +126,7 @@ func MessageHandler(w http.ResponseWriter, r *http.Request) {
}
}

func DecodeAlpacaMessage(r *http.Request) (Data, error) {
var d Data

if err := json.NewDecoder(r.Body).Decode(&d); err != nil {
return Data{}, err
}

return d, nil
}

func ReadConfig(yp string) (*Config, error) {
func ReadConfig(yp string) (*scyllaridae.ServerConfig, error) {
var (
y []byte
err error
Expand All @@ -205,7 +141,7 @@ func ReadConfig(yp string) (*Config, error) {
}
}

var c Config
var c scyllaridae.ServerConfig
err = yaml.Unmarshal(y, &c)
if err != nil {
return nil, err
Expand All @@ -214,13 +150,12 @@ func ReadConfig(yp string) (*Config, error) {
return &c, nil
}

func buildExecCommand(mimetype, addtlArgs string, c *Config) (*exec.Cmd, error) {
var cmdConfig Cmd
func buildExecCommand(mimetype, addtlArgs string, c *scyllaridae.ServerConfig) (*exec.Cmd, error) {
var cmdConfig scyllaridae.Command
var exists bool
slog.Info("Allowed formats", "formats", c.AllowedMimeTypes)
if isAllowedMIMEType(mimetype, c.AllowedMimeTypes) {
cmdConfig, exists = c.CmdByMimeType[mimetype]
if !exists || (len(cmdConfig.Command) == 0) {
if !exists || (len(cmdConfig.Cmd) == 0) {
// Fallback to default if specific MIME type not configured or if command is empty
cmdConfig = c.CmdByMimeType["default"]
}
Expand All @@ -237,7 +172,7 @@ func buildExecCommand(mimetype, addtlArgs string, c *Config) (*exec.Cmd, error)
}
}

cmd := exec.Command(cmdConfig.Command, args...)
cmd := exec.Command(cmdConfig.Cmd, args...)

return cmd, nil
}
Expand Down
Loading

0 comments on commit 04ed5a3

Please sign in to comment.