From 912540c9edcd9168a37d3192102e04e58bb53334 Mon Sep 17 00:00:00 2001 From: Jonas Wagner Date: Fri, 17 May 2024 09:39:13 +0200 Subject: [PATCH] Add Option for Downloading History --- cmd/download.go | 25 ++++++++++++++++++++++--- fhir/client.go | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/cmd/download.go b/cmd/download.go index 79d1643..87e721e 100644 --- a/cmd/download.go +++ b/cmd/download.go @@ -35,6 +35,7 @@ import ( var outputFile string var fhirSearchQuery string +var history bool var usePost bool type commandStats struct { @@ -291,6 +292,15 @@ Examples: ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return resourceTypes, cobra.ShellCompDirectiveNoFileComp }, + PreRunE: func(cmd *cobra.Command, args []string) error { + if history && usePost { + return fmt.Errorf("--history and --post cannot be used together") + } + if history && fhirSearchQuery != "" { + return fmt.Errorf("--history and --query cannot be used together") + } + return nil + }, RunE: func(cmd *cobra.Command, args []string) error { err := createClient() if err != nil { @@ -381,9 +391,17 @@ func downloadResources(client *fhir.Client, resourceType string, fhirSearchQuery request, err = client.NewPostSearchTypeRequest(resourceType, query) } else { if resourceType == "" { - request, err = client.NewSearchSystemRequest(query) + if history { + request, err = client.NewHistorySystemRequest() + } else { + request, err = client.NewSearchSystemRequest(query) + } } else { - request, err = client.NewSearchTypeRequest(resourceType, query) + if history { + request, err = client.NewHistoryTypeRequest(resourceType) + } else { + request, err = client.NewSearchTypeRequest(resourceType, query) + } } } } else { @@ -517,7 +535,7 @@ func writeResources(data *[]byte, sink io.Writer) (int, []*fm.OperationOutcome, var buf bytes.Buffer for _, e := range entries { - if *e.Search.Mode == fm.SearchEntryModeOutcome { + if e.Search != nil && *e.Search.Mode == fm.SearchEntryModeOutcome { outcome, err := fm.UnmarshalOperationOutcome(e.Resource) if err != nil { return resources, inlineOutcomes, fmt.Errorf("could not parse an encountered inline outcome from JSON: %v\n", err) @@ -575,6 +593,7 @@ func init() { downloadCmd.Flags().StringVar(&server, "server", "", "the base URL of the server to use") downloadCmd.Flags().StringVarP(&outputFile, "output-file", "o", "", "write to file instead of stdout") downloadCmd.Flags().StringVarP(&fhirSearchQuery, "query", "q", "", "FHIR search query") + downloadCmd.Flags().BoolVar(&history, "history", false, "Use _history") downloadCmd.Flags().BoolVarP(&usePost, "use-post", "p", false, "use POST to execute the search") _ = downloadCmd.MarkFlagRequired("server") diff --git a/fhir/client.go b/fhir/client.go index 1ab4e02..204a481 100644 --- a/fhir/client.go +++ b/fhir/client.go @@ -179,6 +179,30 @@ func (c *Client) NewSearchSystemRequest(searchQuery url.Values) (*http.Request, return req, nil } +// NewHistoryTypeRequest creates a new search type interaction request that will use GET with a +// FHIR search query in the query params of the URL. +func (c *Client) NewHistoryTypeRequest(resourceType string) (*http.Request, error) { + _url := c.baseURL.JoinPath(resourceType, "_history") + req, err := http.NewRequest("GET", _url.String(), nil) + if err != nil { + return nil, err + } + req.Header.Add("Accept", fhirJson) + return req, nil +} + +// NewHistorySystemRequest creates a new history system interaction request that will use GET on a +// FHIR history endpoint. +func (c *Client) NewHistorySystemRequest() (*http.Request, error) { + _url := c.baseURL.JoinPath("_history") + req, err := http.NewRequest("GET", _url.String(), nil) + if err != nil { + return nil, err + } + req.Header.Add("Accept", fhirJson) + return req, nil +} + // NewPaginatedRequest creates a new resource interaction request based on // a pagination link received from a FHIR server. It sets JSON Accept header and is // otherwise identical to http.NewRequest.