diff --git a/internal/module/http-client.go b/internal/module/http-client.go deleted file mode 100644 index 3c6c056..0000000 --- a/internal/module/http-client.go +++ /dev/null @@ -1,94 +0,0 @@ -package module - -import ( - "context" - "errors" - "log/slog" - "net/http" - "time" - - "github.com/jwetzell/showbridge-go/internal/common" - "github.com/jwetzell/showbridge-go/internal/config" - "github.com/jwetzell/showbridge-go/internal/processor" -) - -type HTTPClient struct { - config config.ModuleConfig - ctx context.Context - client *http.Client - router common.RouteIO - logger *slog.Logger - cancel context.CancelFunc -} - -func init() { - RegisterModule(ModuleRegistration{ - Type: "http.client", - New: func(config config.ModuleConfig) (Module, error) { - - return &HTTPClient{config: config, logger: CreateLogger(config)}, nil - }, - }) -} - -func (hc *HTTPClient) Id() string { - return hc.config.Id -} - -func (hc *HTTPClient) Type() string { - return hc.config.Type -} - -func (hc *HTTPClient) Start(ctx context.Context) error { - hc.logger.Debug("running") - router, ok := ctx.Value(common.RouterContextKey).(common.RouteIO) - - if !ok { - return errors.New("http.client unable to get router from context") - } - hc.router = router - moduleContext, cancel := context.WithCancel(ctx) - hc.ctx = moduleContext - hc.cancel = cancel - - hc.client = &http.Client{ - Timeout: 10 * time.Second, - } - - <-hc.ctx.Done() - hc.logger.Debug("done") - return nil -} - -func (hc *HTTPClient) Output(ctx context.Context, payload any) error { - - payloadRequest, ok := processor.GetAnyAs[*http.Request](payload) - - if !ok { - return errors.New("http.client is only able to output an http.Request") - } - - if hc.client == nil { - return errors.New("http.client client is nil") - } - - response, err := hc.client.Do(payloadRequest) - - if err != nil { - return err - } - - if hc.router != nil { - hc.router.HandleInput(hc.ctx, hc.Id(), response) - } - - return nil -} - -func (hc *HTTPClient) Stop() { - hc.cancel() -} - -func (hc *HTTPClient) Get(key string) (any, error) { - return nil, errors.New("http.client does not support Get") -} diff --git a/internal/module/test/http-client_test.go b/internal/module/test/http-client_test.go deleted file mode 100644 index e2661cf..0000000 --- a/internal/module/test/http-client_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package module_test - -import ( - "testing" - - "github.com/jwetzell/showbridge-go/internal/config" - "github.com/jwetzell/showbridge-go/internal/module" -) - -func TestHTTPClientFromRegistry(t *testing.T) { - registration, ok := module.ModuleRegistry["http.client"] - if !ok { - t.Fatalf("http.client module not registered") - } - - moduleInstance, err := registration.New(config.ModuleConfig{ - Id: "test", - Type: "http.client", - }) - - if err != nil { - t.Fatalf("failed to create http.client module: %s", err) - } - - if moduleInstance.Id() != "test" { - t.Fatalf("http.client module has wrong id: %s", moduleInstance.Id()) - } - - if moduleInstance.Type() != "http.client" { - t.Fatalf("http.client module has wrong type: %s", moduleInstance.Type()) - } -} - -func TestBadHTTPClient(t *testing.T) { - tests := []struct { - name string - params map[string]any - errorString string - }{} - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - - registration, ok := module.ModuleRegistry["http.client"] - if !ok { - t.Fatalf("http.client module not registered") - } - - moduleInstance, err := registration.New(config.ModuleConfig{ - Id: "test", - Type: "http.client", - Params: test.params, - }) - - if err != nil { - if test.errorString != err.Error() { - t.Fatalf("http.client got error '%s', expected '%s'", err.Error(), test.errorString) - } - return - } - - err = moduleInstance.Start(t.Context()) - - if err == nil { - t.Fatalf("http.client expected to fail") - } - - if err.Error() != test.errorString { - t.Fatalf("http.client got error '%s', expected '%s'", err.Error(), test.errorString) - } - }) - } -} diff --git a/internal/processor/http-request-create.go b/internal/processor/http-request-create.go deleted file mode 100644 index 1ca1235..0000000 --- a/internal/processor/http-request-create.go +++ /dev/null @@ -1,70 +0,0 @@ -package processor - -import ( - "bytes" - "context" - "fmt" - "net/http" - "text/template" - - "github.com/jwetzell/showbridge-go/internal/config" -) - -type HTTPRequestCreate struct { - config config.ProcessorConfig - Method string - URL *template.Template -} - -func (hrc *HTTPRequestCreate) Process(ctx context.Context, payload any) (any, error) { - - templateData := GetTemplateData(ctx, payload) - - var urlBuffer bytes.Buffer - err := hrc.URL.Execute(&urlBuffer, templateData) - - if err != nil { - return nil, err - } - - urlString := urlBuffer.String() - - //TODO(jwetzell): support body - request, err := http.NewRequest(hrc.Method, urlString, bytes.NewBuffer([]byte{})) - - if err != nil { - return nil, err - } - - return request, nil -} - -func (hrc *HTTPRequestCreate) Type() string { - return hrc.config.Type -} - -func init() { - RegisterProcessor(ProcessorRegistration{ - Type: "http.request.create", - New: func(config config.ProcessorConfig) (Processor, error) { - params := config.Params - - methodString, err := params.GetString("method") - if err != nil { - return nil, fmt.Errorf("http.request.create method error: %w", err) - } - - urlString, err := params.GetString("url") - if err != nil { - return nil, fmt.Errorf("http.request.create url error: %w", err) - } - - urlTemplate, err := template.New("url").Parse(urlString) - - if err != nil { - return nil, err - } - return &HTTPRequestCreate{config: config, URL: urlTemplate, Method: methodString}, nil - }, - }) -} diff --git a/internal/processor/http-request-do.go b/internal/processor/http-request-do.go new file mode 100644 index 0000000..8bb46bf --- /dev/null +++ b/internal/processor/http-request-do.go @@ -0,0 +1,93 @@ +package processor + +import ( + "bytes" + "context" + "fmt" + "io" + "net/http" + "text/template" + "time" + + "github.com/jwetzell/showbridge-go/internal/config" +) + +type HTTPRequestDo struct { + config config.ProcessorConfig + client *http.Client + Method string + URL *template.Template +} + +func (hrd *HTTPRequestDo) Process(ctx context.Context, payload any) (any, error) { + + templateData := GetTemplateData(ctx, payload) + + var urlBuffer bytes.Buffer + err := hrd.URL.Execute(&urlBuffer, templateData) + + if err != nil { + return nil, err + } + + urlString := urlBuffer.String() + + //TODO(jwetzell): support body + request, err := http.NewRequest(hrd.Method, urlString, bytes.NewBuffer([]byte{})) + + if err != nil { + return nil, err + } + + response, err := hrd.client.Do(request) + + if err != nil { + return nil, err + } + + body, err := io.ReadAll(response.Body) + + if err != nil { + return nil, err + } + + //TODO(jwetzell): support headers, etc + return HTTPResponse{ + Status: response.StatusCode, + Body: body, + }, nil +} + +func (hrd *HTTPRequestDo) Type() string { + return hrd.config.Type +} + +func init() { + RegisterProcessor(ProcessorRegistration{ + Type: "http.request.do", + New: func(config config.ProcessorConfig) (Processor, error) { + params := config.Params + + methodString, err := params.GetString("method") + if err != nil { + return nil, fmt.Errorf("http.request.do method error: %w", err) + } + + urlString, err := params.GetString("url") + if err != nil { + return nil, fmt.Errorf("http.request.do url error: %w", err) + } + + urlTemplate, err := template.New("url").Parse(urlString) + + if err != nil { + return nil, err + } + client := &http.Client{ + Timeout: 10 * time.Second, + } + + return &HTTPRequestDo{config: config, URL: urlTemplate, Method: methodString, client: client}, nil + }, + }) +} diff --git a/internal/processor/test/http-request-create_test.go b/internal/processor/test/http-request-do_test.go similarity index 52% rename from internal/processor/test/http-request-create_test.go rename to internal/processor/test/http-request-do_test.go index 143a84e..19e5250 100644 --- a/internal/processor/test/http-request-create_test.go +++ b/internal/processor/test/http-request-do_test.go @@ -8,13 +8,13 @@ import ( ) func TestHTTPRequestCreateFromRegistry(t *testing.T) { - registration, ok := processor.ProcessorRegistry["http.request.create"] + registration, ok := processor.ProcessorRegistry["http.request.do"] if !ok { - t.Fatalf("http.request.create processor not registered") + t.Fatalf("http.request.do processor not registered") } processorInstance, err := registration.New(config.ProcessorConfig{ - Type: "http.request.create", + Type: "http.request.do", Params: map[string]any{ "method": "GET", "url": "http://example.com", @@ -22,10 +22,10 @@ func TestHTTPRequestCreateFromRegistry(t *testing.T) { }) if err != nil { - t.Fatalf("failed to create http.request.create processor: %s", err) + t.Fatalf("failed to create http.request.do processor: %s", err) } - if processorInstance.Type() != "http.request.create" { - t.Fatalf("http.request.create processor has wrong type: %s", processorInstance.Type()) + if processorInstance.Type() != "http.request.do" { + t.Fatalf("http.request.do processor has wrong type: %s", processorInstance.Type()) } } diff --git a/schema/modules.schema.json b/schema/modules.schema.json index cd5f0b7..ecba5ea 100644 --- a/schema/modules.schema.json +++ b/schema/modules.schema.json @@ -6,21 +6,6 @@ "type": "array", "items": { "oneOf": [ - { - "type": "object", - "title": "HTTP Client", - "properties": { - "id": { - "type": "string", - "minLength": 1 - }, - "type": { - "const": "http.client" - } - }, - "required": ["id", "type"], - "additionalProperties": false - }, { "type": "object", "title": "HTTP Server", diff --git a/schema/processors.schema.json b/schema/processors.schema.json index a187585..3958fc3 100644 --- a/schema/processors.schema.json +++ b/schema/processors.schema.json @@ -203,11 +203,11 @@ }, { "type": "object", - "title": "Create HTTP Request", + "title": "Do HTTP Request", "properties": { "type": { "type": "string", - "const": "http.request.create" + "const": "http.request.do" }, "params": { "type": "object",