// Copyright 2023 schukai GmbH // SPDX-License-Identifier: AGPL-3.0 package jobqueue import ( "bytes" "context" "fmt" "io" "net/http" "sync" ) func NewHTTPRunnableFromMap(data map[string]interface{}) (*HTTPRunnable, error) { url, ok := data["url"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid URL: %v", ErrInvalidData, data["url"]) } method, ok := data["method"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Method: %v", ErrInvalidData, data["method"]) } header, ok := data["header"].(map[string]string) if !ok { return nil, fmt.Errorf("%w: Invalid Header: %v", ErrInvalidData, data["header"]) } body, ok := data["body"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Body: %v", ErrInvalidData, data["body"]) } return &HTTPRunnable{ URL: url, Method: method, Header: header, Body: body, }, nil } // HTTPResult is a result of a http request type HTTPResult struct { StatusCode int Body string } func (h *HTTPResult) GetResult() string { return fmt.Sprintf("StatusCode: %d\n\n%s", h.StatusCode, h.Body) } func (h *HTTPResult) GetError() (string, int) { if h.StatusCode >= 400 { return fmt.Sprintf("StatusCode: %d\n\n%s", h.StatusCode, h.Body), h.StatusCode } return "", 0 } type HTTPRunnable struct { URL string Method string Header map[string]string Body string mu sync.Mutex } func (h *HTTPRunnable) Run(ctx context.Context) (RunResult[HTTPResult], error) { client := &http.Client{} reqBody := bytes.NewBufferString(h.Body) req, err := http.NewRequestWithContext(ctx, h.Method, h.URL, reqBody) if err != nil { return RunResult[HTTPResult]{Status: ResultStatusFailed}, err } for key, value := range h.Header { req.Header.Set(key, value) } resp, err := client.Do(req) if err != nil { return RunResult[HTTPResult]{Status: ResultStatusFailed}, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return RunResult[HTTPResult]{Status: ResultStatusFailed}, err } return RunResult[HTTPResult]{ Status: ResultStatusSuccess, Data: HTTPResult{ StatusCode: resp.StatusCode, Body: string(body), }, }, nil } func (h *HTTPRunnable) GetType() string { return "http" } func (h *HTTPRunnable) GetPersistence() RunnableImport { h.mu.Lock() defer h.mu.Unlock() data := JSONMap{ "url": h.URL, "method": h.Method, "header": h.Header, "body": h.Body, } return RunnableImport{ Type: h.GetType(), Data: data, } }