Skip to content

Commit

Permalink
Convert patient request body to url encoded params (#1000)
Browse files Browse the repository at this point in the history
## 🎫 Ticket

An extension of https://jira.cms.gov/browse/BCDA-8230

## 🛠 Changes

Converted patient request body to url encoded params as requested by
BFD.

## ℹ️ Context

<!-- Why were these changes made? Add background context suitable for a
non-technical audience. -->

<!-- If any of the following security implications apply, this PR must
not be merged without Stephen Walter's approval. Explain in this section
and add @SJWalter11 as a reviewer.
  - Adds a new software dependency or dependencies.
  - Modifies or invalidates one or more of our security controls.
  - Stores or transmits data that was not stored or transmitted before.
- Requires additional review of security implications for other reasons.
-->

## 🧪 Validation

Local linting and testing.
  • Loading branch information
carlpartridge authored Oct 9, 2024
1 parent 9999a37 commit 094dc12
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 14 deletions.
21 changes: 14 additions & 7 deletions bcda/client/bluebutton.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,17 @@ func (bbc *BlueButtonClient) GetPatient(jobData models.JobEnqueueArgs, patientID
}

func (bbc *BlueButtonClient) GetPatientByMbi(jobData models.JobEnqueueArgs, mbi string) (string, error) {
headers := make(http.Header)
headers.Add("Content-Type", "application/x-www-form-urlencoded")
params := url.Values{}
params.Set("identifier", fmt.Sprintf("http://hl7.org/fhir/sid/us-mbi|%s", mbi))

u, err := bbc.getURL("Patient/_search", params)
if err != nil {
return "", err
}

body := fmt.Sprintf(`{"identifier":"http://hl7.org/fhir/sid/us-mbi|%s"}`, mbi)
return bbc.getRawData(jobData, "POST", u, strings.NewReader(body))
return bbc.getRawData("POST", jobData, u, headers, strings.NewReader(params.Encode()))
}

func (bbc *BlueButtonClient) GetCoverage(jobData models.JobEnqueueArgs, beneficiaryID string) (*fhirModels.Bundle, error) {
Expand Down Expand Up @@ -249,7 +251,7 @@ func (bbc *BlueButtonClient) GetMetadata() (string, error) {
}
jobData := models.JobEnqueueArgs{}

return bbc.getRawData(jobData, "GET", u, nil)
return bbc.getRawData("GET", jobData, u, nil, nil)
}

func (bbc *BlueButtonClient) makeBundleDataRequest(method string, u *url.URL, jobData models.JobEnqueueArgs, headers http.Header, body io.Reader) (*fhirModels.Bundle, error) {
Expand Down Expand Up @@ -300,9 +302,7 @@ func (bbc *BlueButtonClient) tryBundleRequest(method string, u *url.URL, jobData
req.Header.Add(key, value)
}
}

queryID := uuid.NewRandom()
addDefaultRequestHeaders(req, queryID, jobData)
addDefaultRequestHeaders(req, uuid.NewRandom(), jobData)

result, nextURL, err = bbc.client.DoBundleRequest(req)
if err != nil {
Expand All @@ -323,7 +323,7 @@ func (bbc *BlueButtonClient) tryBundleRequest(method string, u *url.URL, jobData
return result, nextURL, nil
}

func (bbc *BlueButtonClient) getRawData(jobData models.JobEnqueueArgs, method string, u *url.URL, body io.Reader) (string, error) {
func (bbc *BlueButtonClient) getRawData(method string, jobData models.JobEnqueueArgs, u *url.URL, headers http.Header, body io.Reader) (string, error) {
m := monitoring.GetMonitor()
txn := m.Start(u.Path, nil, nil)
defer m.End(txn)
Expand All @@ -340,8 +340,15 @@ func (bbc *BlueButtonClient) getRawData(jobData models.JobEnqueueArgs, method st
logger.Error(err)
return err
}

req = newrelic.RequestWithTransactionContext(req, txn)
for key, values := range headers {
for _, value := range values {
req.Header.Add(key, value)
}
}
addDefaultRequestHeaders(req, uuid.NewRandom(), jobData)

result, err = bbc.client.DoRaw(req)
if err != nil {
logger.Error(err)
Expand Down
21 changes: 14 additions & 7 deletions bcda/client/bluebutton_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client_test

import (
"bytes"
"compress/gzip"
"fmt"
"io"
Expand Down Expand Up @@ -577,7 +578,9 @@ func (s *BBRequestTestSuite) TestValidateRequest() {
noIncludeAddressFieldsChecker,
noIncludeTaxNumbersChecker,
noBulkRequestHeaders,
hasDefaultRequestHeadersNoQuery,
hasDefaultRequestHeaders,
hasContentTypeURLEncodedHeader,
hasURLEncodedBodyWithIdentifier,
},
},
{
Expand Down Expand Up @@ -949,12 +952,16 @@ func hasDefaultRequestHeaders(t *testing.T, req *http.Request) {
assert.NotEmpty(t, req.Header.Get(constants.BBHeaderOriginQ))
assert.NotEmpty(t, req.Header.Get(constants.BBHeaderOriginQC))
}
func hasDefaultRequestHeadersNoQuery(t *testing.T, req *http.Request) {
assert.NotEmpty(t, req.Header.Get(constants.BBHeaderTS))
assert.NotEmpty(t, req.Header.Get(constants.BBHeaderOriginURL))
assert.NotEmpty(t, req.Header.Get(constants.BBHeaderOriginQID))
assert.Empty(t, req.Header.Get(constants.BBHeaderOriginQ))
assert.NotEmpty(t, req.Header.Get(constants.BBHeaderOriginQC))
func hasContentTypeURLEncodedHeader(t *testing.T, req *http.Request) {
assert.Equal(t, "application/x-www-form-urlencoded", req.Header.Get("Content-Type"))
}
func hasURLEncodedBodyWithIdentifier(t *testing.T, req *http.Request) {
buf := new(bytes.Buffer)
buf.ReadFrom(req.Body)
respBytes := buf.String()
body := string(respBytes)

assert.Contains(t, body, fmt.Sprintf("identifier=%s", url.QueryEscape("http://hl7.org/fhir/sid/us-mbi|")))
}
func hasBulkRequestHeaders(t *testing.T, req *http.Request) {
assert.NotEmpty(t, req.Header.Get(jobIDHeader))
Expand Down

0 comments on commit 094dc12

Please sign in to comment.