### Basic Foundry Function Handler in Go Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md A minimal Go program demonstrating how to set up a Foundry function handler using the foundry-fn-go SDK. It includes basic routing for GET and POST requests and demonstrates configuration handling. ```go package main import ( "context" "errors" "log/slog" "net/http" fdk "github.com/CrowdStrike/foundry-fn-go" ) func main() { fdk.Run(context.Background(), newHandler) } type request struct { Name string `json:"name"` Val string `json:"val"` } // newHandler here is showing how a config is integrated. It is using generics, // so we can unmarshal the config into a concrete type and then validate it. The // OK method is run to validate the contents of the config. func newHandler(_ context.Context, logger *slog.Logger, cfg config) fdk.Handler { mux := fdk.NewMux() mux.Get("/name", fdk.HandlerFn(func(_ context.Context, r fdk.Request) fdk.Response { return fdk.Response{ Body: fdk.JSON(map[string]string{"name": r.Params.Query.Get("name")}), Code: 200, } })) mux.Post("/echo", fdk.HandlerFnOfOK(func(_ context.Context, r fdk.RequestOf[request]) fdk.Response { if r.Body.Name == "kaboom" { logger.Error("encountered the kaboom") } return fdk.Response{ Body: fdk.JSON(r.Body), Code: 201, Header: http.Header{"X-Cs-Method": []string{r.Method}}, } })) return mux } type config struct { Int int `json:"integer"` Str string `json:"string"` } func (c config) OK() error { var errs []error if c.Int < 1 { errs = append(errs, errors.New("integer must be greater than 0")) } if c.Str == "" { errs = append(errs, errors.New("non empty string must be provided")) } return errors.Join(errs...) } ``` -------------------------------- ### Install Foundry-fn-go SDK via go get Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md Installs or updates the CrowdStrike Foundry Function as a Service Go SDK using the go get command. ```shell go get github.com/CrowdStrike/foundry-fn-go ``` -------------------------------- ### Test Handler Integration with Schemas Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md Provides an example of using `fdktest.HandlerSchemaOK` to validate a handler's integration with request and response JSON schemas. This is useful for ensuring data integrity and correct API interactions. ```go package somefn_test import ( "context" "net/http" "testing" fdk "github.com/CrowdStrike/foundry-fn-go" "github.com/CrowdStrike/foundry-fn-go/fdktest" ) func TestHandlerIntegration(t *testing.T) { reqSchema := `{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "postalCode": { "type": "string", "description": "The person's first name.", "pattern": "\\d{5}" }, "optional": { "type": "string", "description": "The person's last name." } }, "required": [ "postalCode" ] }` respSchema := `{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "foo": { "type": "string", "description": "The person's first name.", "enum": ["bar"] } }, "required": [ "foo" ] }` handler := fdk.HandlerFn(func(ctx context.Context, r fdk.Request) fdk.Response { return fdk.Response{Body: fdk.JSON(map[string]string{"foo": "bar"})} }) req := fdk.Request{ URL: "/", Method: http.MethodPost, Body: json.RawMessage(`{"postalCode": "55755"}`), } err := fdktest.HandlerSchemaOK(handler, req, reqSchema, respSchema) if err != nil { t.Fatal("unexpected err: ", err) } } ``` -------------------------------- ### Local Testing of Foundry Function Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md Instructions for building and running a Foundry function locally, including how to provide configuration and send test requests using curl. ```shell # build the project which uses the sdk cd my-project && go mod tidy && go build -o run_me . # run the executable. config should be in json format here. CS_FN_CONFIG_PATH=$PATH_TO_CONFIG_JSON ./run_me curl -X POST http://localhost:8081/ \ -H "Content-Type: application/json" \ --data '{ "body": { "foo": "bar" }, "method": "POST", "url": "/greetings" }' ``` -------------------------------- ### Create Falcon Client with gofalcon Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md Demonstrates how to create a CrowdStrike Falcon API client using the gofalcon library within a Foundry Function. It shows the necessary imports and the function signature for creating the client. ```go package main import ( "context" "log/slog" fdk "github.com/CrowdStrike/foundry-fn-go" "github.com/crowdstrike/gofalcon/falcon" "github.com/crowdstrike/gofalcon/falcon/client" ) func newHandler(_ context.Context, _ *slog.Logger, cfg config) fdk.Handler { mux := fdk.NewMux() mux.Post("/echo", fdk.HandlerFn(func(ctx context.Context, r fdk.Request) fdk.Response { client, err := newFalconClient(ctx, r.AccessToken) if err != nil { return fdk.ErrResp(fdk.APIError{Code: 500, Message: err.Error()}) } // we have a valid gofalcon client })) return mux } func newFalconClient(ctx context.Context, token string) (*client.CrowdStrikeAPISpecification, error) { opts := fdk.FalconClientOpts() return falcon.NewClient(&falcon.ApiConfig{ AccessToken: token, Cloud: falcon.Cloud(opts.Cloud), Context: ctx, UserAgentOverride: opts.UserAgent, }) } // omitting rest of implementation ``` -------------------------------- ### Build Foundry-fn-go SDK from Source Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md Builds the CrowdStrike Foundry Function as a Service Go SDK from source using standard Go build commands. ```shell go mod tidy go build . ``` -------------------------------- ### Proper Error Handling in Foundry Functions Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md Illustrates the recommended approach for handling errors in Foundry Functions by returning an error response instead of using `os.Exit`. This ensures that errors are communicated back to the caller gracefully. ```go package main import ( "context" "log/slog" "net/http" fdk "github.com/CrowdStrike/foundry-fn-go" ) func newHandler(_ context.Context, logger *slog.Logger, _ fdk.SkipCfg) fdk.Handler { foo, err := newFoo() if err != nil { // leave yourself/author the nitty-gritty details and return to the end user/caller // a valid error that doesn't expose all the implementation details logger.Error("failed to create foo", "err", err.Error()) return fdk.ErrHandler(fdk.APIError{Code: http.StatusInternalServerError, Message: "unexpected error starting function"}) } mux := fdk.NewMux() // ...trim rest of setup return mux } ``` -------------------------------- ### Handle Falcon Fusion Workflows Source: https://github.com/crowdstrike/foundry-fn-go/blob/main/README.md Shows how to integrate Foundry Functions with Falcon Fusion workflows using `HandleWorkflow` and `HandleWorkflowOf`. These helpers simplify context decoding and request handling for workflow events. ```go package somefn import ( "context" "log/slog" fdk "github.com/CrowdStrike/foundry-fn-go" ) type reqBody struct { Foo string `json:"foo"` } func New(ctx context.Context, _ *slog.Logger, _ fdk.SkipCfg) fdk.Handler { m := fdk.NewMux() // for get/delete reqs use HandleWorkflow. The path is just an examples, any payh can be used. m.Get("/workflow", fdk.HandleWorkflow(func(ctx context.Context, r fdk.Request, workflowCtx fdk.WorkflowCtx) fdk.Response { // ... trim impl })) // for handlers that expect a request body (i.e. PATCH/POST/PUT) m.Post("/workflow", fdk.HandleWorkflowOf(func(ctx context.Context, r fdk.RequestOf[reqBody], workflowCtx fdk.WorkflowCtx) fdk.Response { // .. trim imple })) return m } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.