[AMD Official Use Only - General] Reviewed-by: Abner Chang <abner.ch...@amd.com>
> -----Original Message----- > From: Nickle Wang <nickle.w...@hpe.com> > Sent: Wednesday, July 27, 2022 9:38 AM > To: devel@edk2.groups.io > Cc: Chang, Abner <abner.ch...@amd.com>; Yang, Atom > <atom.y...@amd.com>; Nick Ramirez <nrami...@nvidia.com> > Subject: [edk2-staging][PATCH v3 09/15] edk2-staging/RedfishClientPkg: > Update RedfishLib > > [CAUTION: External Email] > > RedfishLib has no capability to return HTTP header in response. > However, feature driver needs to know the information like "ETag" or > "Location" in HTTP response header per Redfish specification. Add > corresponding function to return HTTP header in response data. > > Signed-off-by: Nickle Wang <nickle.w...@hpe.com> > Cc: Abner Chang <abner.ch...@amd.com> > Cc: Yang Atom <atom.y...@amd.com> > Cc: Nick Ramirez <nrami...@nvidia.com> > --- > .../PrivateLibrary/RedfishLib/RedfishLib.c | 12 +- > .../edk2libredfish/include/redfishPayload.h | 5 +- > .../edk2libredfish/include/redfishService.h | 5 +- > .../RedfishLib/edk2libredfish/src/payload.c | 90 ++- > .../RedfishLib/edk2libredfish/src/service.c | 554 +++++++++++++++++- > 5 files changed, 657 insertions(+), 9 deletions(-) > > diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c > b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c > index 18aa4646e8..b8ca493e24 100644 > --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c > +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c > @@ -3,7 +3,7 @@ > (CRUD) Redfish resources and provide basic query. > > Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> > - (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -323,7 +323,7 @@ RedfishGetByUri ( > > ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE)); > > - JsonValue = getUriFromService (RedfishService, Uri, &RedResponse- > >StatusCode); > + JsonValue = getUriFromServiceEx (RedfishService, Uri, > + &RedResponse->Headers, &RedResponse->HeaderCount, > + &RedResponse->StatusCode); > RedResponse->Payload = createRedfishPayload(JsonValue, RedfishService); > > // > @@ -541,9 +541,11 @@ RedfishPatchToPayload ( > > ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE)); > > - RedResponse->Payload = (REDFISH_PAYLOAD) patchPayload ( > + RedResponse->Payload = (REDFISH_PAYLOAD) patchPayloadEx ( > Target, > Payload, > + &RedResponse->Headers, > + &RedResponse->HeaderCount, > &(RedResponse->StatusCode) > ); > > @@ -607,9 +609,11 @@ RedfishPostToPayload ( > > ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE)); > > - RedResponse->Payload = (REDFISH_PAYLOAD) postPayload ( > + RedResponse->Payload = (REDFISH_PAYLOAD) postPayloadEx ( > Target, > Payload, > + &RedResponse->Headers, > + &RedResponse->HeaderCount, > &(RedResponse->StatusCode) > ); > > diff --git > a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish > Payload.h > b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish > Payload.h > index 43149f3c89..be74c64297 100644 > --- > a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish > Payload.h > +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/ > +++ redfishPayload.h > @@ -9,7 +9,7 @@ > > //---------------------------------------------------------------------------- > > Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> > - (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -29,8 +29,11 @@ redfishPayload* getPayloadByIndex(redfishPayload* > payload, size_t index, EFI_HTT > redfishPayload* getPayloadForPath(redfishPayload* payload, > redPathNode* redpath, EFI_HTTP_STATUS_CODE** StatusCode); > redfishPayload* getPayloadForPathString(redfishPayload* payload, const > char* string, EFI_HTTP_STATUS_CODE** StatusCode); > redfishPayload* patchPayload(redfishPayload* target, redfishPayload* > payload, EFI_HTTP_STATUS_CODE** StatusCode); > +redfishPayload* patchPayloadEx(redfishPayload* target, redfishPayload* > +payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > +EFI_HTTP_STATUS_CODE** StatusCode); > redfishPayload* postContentToPayload(redfishPayload* target, const char* > data, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE** > StatusCode); > +redfishPayload* postContentToPayloadEx(redfishPayload* target, const > +char* data, size_t dataSize, const char* contentType, EFI_HTTP_HEADER > +**Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** > StatusCode); > redfishPayload* postPayload(redfishPayload* target, redfishPayload* > payload, EFI_HTTP_STATUS_CODE** StatusCode); > +redfishPayload* postPayloadEx(redfishPayload* target, redfishPayload* > +payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > +EFI_HTTP_STATUS_CODE** StatusCode); > void cleanupPayload(redfishPayload* payload); > bool isPayloadCollection (redfishPayload *Payload); > size_t getCollectionSize(redfishPayload* payload); > diff --git > a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish > Service.h > b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish > Service.h > index 0215caccfc..3d87fad85a 100644 > --- > a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish > Service.h > +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/ > +++ redfishService.h > @@ -9,7 +9,7 @@ > > //---------------------------------------------------------------------------- > > Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> > - (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -91,8 +91,11 @@ typedef struct { > #define REDFISH_FLAG_SERVICE_NO_VERSION_DOC 0x00000001 //The > Redfish Service lacks the version document (in violation of the Redfish spec) > redfishService* > createServiceEnumerator(REDFISH_CONFIG_SERVICE_INFORMATION > *RedfishConfigServiceInfo, const char* rootUri, enumeratorAuthentication* > auth, unsigned int flags); > json_t* getUriFromService(redfishService* service, const char* uri, > EFI_HTTP_STATUS_CODE** StatusCode); > +json_t* getUriFromServiceEx(redfishService* service, const char* uri, > +EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > EFI_HTTP_STATUS_CODE > +**StatusCode); > json_t* patchUriFromService(redfishService* service, const char* uri, const > char* content, EFI_HTTP_STATUS_CODE** StatusCode); > +json_t* patchUriFromServiceEx(redfishService* service, const char* uri, > +const char* content, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > +EFI_HTTP_STATUS_CODE** StatusCode); > json_t* postUriFromService(redfishService* service, const char* uri, const > char* content, size_t contentLength, const char* contentType, > EFI_HTTP_STATUS_CODE** StatusCode); > +json_t* postUriFromServiceEx(redfishService* service, const char* uri, > +const char* content, size_t contentLength, const char* contentType, > +EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > EFI_HTTP_STATUS_CODE** > +StatusCode); > json_t* deleteUriFromService(redfishService* service, const char* uri, > EFI_HTTP_STATUS_CODE** StatusCode); > redfishPayload* getRedfishServiceRoot(redfishService* service, const char* > version, EFI_HTTP_STATUS_CODE** StatusCode); > redfishPayload* getPayloadByPath(redfishService* service, const char* path, > EFI_HTTP_STATUS_CODE** StatusCode); diff --git > a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c > b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c > index bd8d143c4e..8b49bec0df 100644 > --- > a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c > +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payl > +++ oad.c > @@ -9,7 +9,7 @@ > > //---------------------------------------------------------------------------- > > Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> > - (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -326,6 +326,40 @@ redfishPayload* > getPayloadForPathString(redfishPayload* payload, const char* str > return ret; > } > > +redfishPayload* patchPayloadEx(redfishPayload* target, redfishPayload* > +payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > +EFI_HTTP_STATUS_CODE** StatusCode) { > + json_t* json; > + char* content; > + char* uri; > + > + if(!target || !payload || StatusCode == NULL) { > + return NULL; > + } > + > + *StatusCode = NULL; > + > + json = json_object_get(target->json, "@odata.id"); if(json == NULL) > + { > + return NULL; > + } > + uri = strdup(json_string_value(json)); > + > + content = json_dumps(payload->json, 0); json_decref(json); > + > + json = patchUriFromServiceEx(target->service, uri, content, Headers, > + HeaderCount, StatusCode); free(uri); free(content); if(json == > + NULL) { > + return NULL; > + } > + > + return createRedfishPayload(json, target->service); } > + > redfishPayload* patchPayload(redfishPayload* target, redfishPayload* > payload, EFI_HTTP_STATUS_CODE** StatusCode) { > json_t* json; > @@ -360,6 +394,38 @@ redfishPayload* patchPayload(redfishPayload* > target, redfishPayload* payload, EF > return createRedfishPayload(json, target->service); } > > +redfishPayload* postContentToPayloadEx(redfishPayload* target, const > +char* data, size_t dataSize, const char* contentType, EFI_HTTP_HEADER > **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** StatusCode) > { > + json_t* json; > + char* uri; > + > + if(!target || !data || StatusCode == NULL) > + { > + return NULL; > + } > + > + *StatusCode = NULL; > + > + json = json_object_get(target->json, "@odata.id"); > + if(json == NULL) > + { > + json = json_object_get(target->json, "target"); > + if(json == NULL) > + { > + return NULL; > + } > + } > + uri = strdup(json_string_value(json)); > + json = postUriFromServiceEx(target->service, uri, data, dataSize, > contentType, Headers, HeaderCount, StatusCode); > + free(uri); > + if(json == NULL) > + { > + return NULL; > + } > + > + return createRedfishPayload(json, target->service); } > + > redfishPayload* postContentToPayload(redfishPayload* target, const char* > data, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE** > StatusCode) { > json_t* json; > @@ -392,6 +458,28 @@ redfishPayload* > postContentToPayload(redfishPayload* target, const char* data, s > return createRedfishPayload(json, target->service); } > > +redfishPayload* postPayloadEx(redfishPayload* target, redfishPayload* > +payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > EFI_HTTP_STATUS_CODE** StatusCode) { > + char* content; > + redfishPayload* ret; > + > + if(!target || !payload || StatusCode == NULL) > + { > + return NULL; > + } > + > + *StatusCode = NULL; > + > + if(!json_is_object(payload->json)) > + { > + return NULL; > + } > + content = payloadToString(payload, false); > + ret = postContentToPayloadEx(target, content, strlen(content), NULL, > Headers, HeaderCount, StatusCode); > + free(content); > + return ret; > +} > + > redfishPayload* postPayload(redfishPayload* target, redfishPayload* > payload, EFI_HTTP_STATUS_CODE** StatusCode) { > char* content; > diff --git > a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c > b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c > index 7713f89e6d..450fa78bbd 100644 > --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c > +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/serv > +++ ice.c > @@ -9,7 +9,7 @@ > > //---------------------------------------------------------------------------- > > Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> > - (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> > + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR> > > SPDX-License-Identifier: BSD-2-Clause-Patent > > @@ -338,6 +338,190 @@ ON_EXIT: > return ret; > } > > +EFI_HTTP_HEADER *cloneHttpHeaders(EFI_HTTP_MESSAGE *message, > UINTN > +*HeaderCount) { > + EFI_HTTP_HEADER *Buffer; > + UINTN Index; > + > + if (message == NULL || HeaderCount == NULL) { > + return NULL; > + } > + > + *HeaderCount = message->HeaderCount; > + Buffer = AllocatePool (sizeof (EFI_HTTP_HEADER) * > + message->HeaderCount); if (Buffer == NULL) { > + return NULL; > + } > + > + for (Index = 0; Index < message->HeaderCount; Index++) { > + Buffer[Index].FieldName = AllocateCopyPool (AsciiStrSize (message- > >Headers[Index].FieldName), message->Headers[Index].FieldName); > + ASSERT (Buffer[Index].FieldName != NULL); > + Buffer[Index].FieldValue = AllocateCopyPool (AsciiStrSize (message- > >Headers[Index].FieldValue), message->Headers[Index].FieldValue); > + ASSERT (Buffer[Index].FieldValue != NULL); } > + > + return Buffer; > +} > + > +json_t* getUriFromServiceEx(redfishService* service, const char* uri, > +EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > EFI_HTTP_STATUS_CODE > +**StatusCode) { > + char* url; > + json_t* ret; > + HTTP_IO_HEADER *HttpIoHeader = NULL; > + EFI_STATUS Status; > + EFI_HTTP_REQUEST_DATA *RequestData = NULL; > + EFI_HTTP_MESSAGE *RequestMsg = NULL; > + EFI_HTTP_MESSAGE ResponseMsg; > + EFI_HTTP_HEADER *ContentEncodedHeader; > + > + if(service == NULL || uri == NULL || Headers == NULL || HeaderCount > + == NULL ||StatusCode == NULL) { > + return NULL; > + } > + > + *StatusCode = NULL; > + *HeaderCount = 0; > + *Headers = NULL; > + > + url = makeUrlForService(service, uri); > + if(!url) > + { > + return NULL; > + } > + > + DEBUG((DEBUG_INFO, "libredfish: getUriFromServiceEx(): %a\n", url)); > + > + // > + // Step 1: Create HTTP request message with 4 headers: > + // > + HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || > + service->basicAuthStr) ? 6 : 5); if (HttpIoHeader == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + if(service->sessionToken) > + { > + Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service- > >sessionToken); > + ASSERT_EFI_ERROR (Status); > + } else if (service->basicAuthStr) { > + Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service- > >basicAuthStr); > + ASSERT_EFI_ERROR (Status); > + } > + > + Status = HttpIoSetHeader (HttpIoHeader, "Host", > + service->HostHeaderValue); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0"); > + ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader, > + "Accept", "application/json"); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish"); > + ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader, > + "Connection", "Keep-Alive"); ASSERT_EFI_ERROR (Status); > + > + // > + // Step 2: build the rest of HTTP request info. > + // > + RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA)); if > + (RequestData == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + RequestData->Method = HttpMethodGet; > + RequestData->Url = C8ToC16 (url); > + > + // > + // Step 3: fill in EFI_HTTP_MESSAGE > + // > + RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE)); if > + (RequestMsg == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + RequestMsg->Data.Request = RequestData; RequestMsg->HeaderCount > = > + HttpIoHeader->HeaderCount; > + RequestMsg->Headers = HttpIoHeader->Headers; > + > + ZeroMem (&ResponseMsg, sizeof (ResponseMsg)); > + > + // > + // Step 4: call RESTEx to get response from REST service. > + // > + Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, > + &ResponseMsg); if (EFI_ERROR (Status)) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + // > + // Step 5: Return the HTTP StatusCode and Body message. > + // > + if (ResponseMsg.Data.Response != NULL) { > + *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE)); > + if (*StatusCode == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + // > + // The caller shall take the responsibility to free the buffer. > + // > + **StatusCode = ResponseMsg.Data.Response->StatusCode; > + } > + > + if (ResponseMsg.Headers != NULL) { > + *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount); } > + > + if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) { > + // > + // Check if data is encoded. > + // > + ContentEncodedHeader = HttpFindHeader (ResponseMsg.HeaderCount, > ResponseMsg.Headers, HTTP_HEADER_CONTENT_ENCODING); > + if (ContentEncodedHeader != NULL) { > + // > + // The content is encoded. > + // > + Status = DecodeResponseContent (ContentEncodedHeader->FieldValue, > &ResponseMsg.Body, &ResponseMsg.BodyLength); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Failed to decompress the response > content %r\n.", __FUNCTION__, Status)); > + ret = NULL; > + goto ON_EXIT; > + } > + } > + ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, > + NULL); } else { > + // > + // There is no message body returned from server. > + // > + ret = NULL; > + } > + > +ON_EXIT: > + if (url != NULL) { > + free (url); > + } > + > + if (HttpIoHeader != NULL) { > + HttpIoFreeHeader (HttpIoHeader); > + } > + > + if (RequestData != NULL) { > + RestConfigFreeHttpRequestData (RequestData); } > + > + if (RequestMsg != NULL) { > + FreePool (RequestMsg); > + } > + > + RestConfigFreeHttpMessage (&ResponseMsg, FALSE); > + > + return ret; > +} > + > json_t* getUriFromService(redfishService* service, const char* uri, > EFI_HTTP_STATUS_CODE** StatusCode) { > char* url; > @@ -491,7 +675,7 @@ ON_EXIT: > return ret; > } > > -json_t* patchUriFromService(redfishService* service, const char* uri, const > char* content, EFI_HTTP_STATUS_CODE** StatusCode) > +json_t* patchUriFromServiceEx(redfishService* service, const char* uri, > +const char* content, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > +EFI_HTTP_STATUS_CODE** StatusCode) > { > char* url; > json_t* ret; > @@ -632,6 +816,10 @@ json_t* patchUriFromService(redfishService* > service, const char* uri, const char > **StatusCode = ResponseMsg.Data.Response->StatusCode; > } > > + if (ResponseMsg.Headers != NULL) { > + *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount); } > + > if (EncodedContent != content) { > FreePool (EncodedContent); > } > @@ -668,6 +856,368 @@ ON_EXIT: > return ret; > } > > +json_t* patchUriFromService(redfishService* service, const char* uri, > +const char* content, EFI_HTTP_STATUS_CODE** StatusCode) { > + char* url; > + json_t* ret; > + HTTP_IO_HEADER *HttpIoHeader = NULL; > + EFI_STATUS Status; > + EFI_HTTP_REQUEST_DATA *RequestData = NULL; > + EFI_HTTP_MESSAGE *RequestMsg = NULL; > + EFI_HTTP_MESSAGE ResponseMsg; > + CHAR8 ContentLengthStr[80]; > + CHAR8 *EncodedContent; > + UINTN EncodedContentLen; > + > + if(service == NULL || uri == NULL || content == NULL || StatusCode == > + NULL) { > + return NULL; > + } > + > + *StatusCode = NULL; > + > + url = makeUrlForService(service, uri); > + if(!url) > + { > + return NULL; > + } > + > + DEBUG((DEBUG_INFO, "libredfish: patchUriFromService(): %a\n", url)); > + > + // > + // Step 1: Create HTTP request message with 4 headers: > + // > + HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || > + service->basicAuthStr) ? 9 : 8); if (HttpIoHeader == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + if(service->sessionToken) > + { > + Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service- > >sessionToken); > + ASSERT_EFI_ERROR (Status); > + } else if (service->basicAuthStr) { > + Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service- > >basicAuthStr); > + ASSERT_EFI_ERROR (Status); > + } > + > + Status = HttpIoSetHeader (HttpIoHeader, "Host", > + service->HostHeaderValue); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json"); > + ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader, > + "Accept", "application/json"); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish"); > + ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader, > + "Connection", "Keep-Alive"); ASSERT_EFI_ERROR (Status); > + > + AsciiSPrint( > + ContentLengthStr, > + sizeof (ContentLengthStr), > + "%lu", > + (UINT64) strlen(content) > + ); > + Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", > + ContentLengthStr); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0"); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Step 2: build the rest of HTTP request info. > + // > + RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA)); if > + (RequestData == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + RequestData->Method = HttpMethodPatch; RequestData->Url = C8ToC16 > + (url); > + > + // > + // Step 3: fill in EFI_HTTP_MESSAGE > + // > + RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE)); if > + (RequestMsg == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + EncodedContent = (CHAR8 *)content; > + EncodedContentLen = strlen(content); > + // > + // We currently only support gzip Content-Encoding. > + // > + Status = EncodeRequestContent ((CHAR8 > *)HTTP_CONTENT_ENCODING_GZIP, > + (CHAR8 *)content, (VOID **)&EncodedContent, &EncodedContentLen); if > (Status == EFI_INVALID_PARAMETER) { > + DEBUG((DEBUG_ERROR, "%a: Error to encode content.\n", > __FUNCTION__)); > + ret = NULL; > + goto ON_EXIT; > + } else if (Status == EFI_UNSUPPORTED) { > + DEBUG((DEBUG_INFO, "No content coding for %a! Use raw data > instead.\n", HTTP_CONTENT_ENCODING_GZIP)); > + Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding", > HTTP_CONTENT_ENCODING_IDENTITY); > + ASSERT_EFI_ERROR (Status); > + } else { > + Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding", > HTTP_CONTENT_ENCODING_GZIP); > + ASSERT_EFI_ERROR (Status); > + } > + > + RequestMsg->Data.Request = RequestData; RequestMsg->HeaderCount > = > + HttpIoHeader->HeaderCount; > + RequestMsg->Headers = HttpIoHeader->Headers; > + RequestMsg->BodyLength = EncodedContentLen; > + RequestMsg->Body = (VOID*) EncodedContent; > + > + ZeroMem (&ResponseMsg, sizeof (ResponseMsg)); > + > + // > + // Step 4: call RESTEx to get response from REST service. > + // > + Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, > + &ResponseMsg); if (EFI_ERROR (Status)) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + // > + // Step 5: Return the HTTP StatusCode and Body message. > + // > + if (ResponseMsg.Data.Response != NULL) { > + *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE)); > + if (*StatusCode == NULL) { > + ret = NULL; > + goto ON_EXIT; > + } > + > + // > + // The caller shall take the responsibility to free the buffer. > + // > + **StatusCode = ResponseMsg.Data.Response->StatusCode; > + } > + > + if (EncodedContent != content) { > + FreePool (EncodedContent); > + } > + > + > + if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) { > + ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, > + NULL); } else { > + // > + // There is no message body returned from server. > + // > + ret = NULL; > + } > + > +ON_EXIT: > + if (url != NULL) { > + free (url); > + } > + > + if (HttpIoHeader != NULL) { > + HttpIoFreeHeader (HttpIoHeader); > + } > + > + if (RequestData != NULL) { > + RestConfigFreeHttpRequestData (RequestData); } > + > + if (RequestMsg != NULL) { > + FreePool (RequestMsg); > + } > + > + RestConfigFreeHttpMessage (&ResponseMsg, FALSE); > + > + return ret; > +} > + > +json_t* postUriFromServiceEx(redfishService* service, const char* uri, > +const char* content, size_t contentLength, const char* contentType, > EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, > EFI_HTTP_STATUS_CODE** StatusCode) { > + char* url = NULL; > + json_t* ret; > + HTTP_IO_HEADER *HttpIoHeader = NULL; > + EFI_STATUS Status; > + EFI_HTTP_REQUEST_DATA *RequestData = NULL; > + EFI_HTTP_MESSAGE *RequestMsg = NULL; > + EFI_HTTP_MESSAGE ResponseMsg; > + CHAR8 ContentLengthStr[80]; > + EFI_HTTP_HEADER *HttpHeader = NULL; > + > + ret = NULL; > + > + if(service == NULL || uri == NULL || content == NULL || StatusCode == > + NULL) { > + return NULL; > + } > + > + *StatusCode = NULL; > + > + url = makeUrlForService(service, uri); > + if(!url) > + { > + return NULL; > + } > + > + DEBUG((DEBUG_INFO, "libredfish: postUriFromService(): %a\n", url)); > + > + if(contentLength == 0) > + { > + contentLength = strlen(content); > + } > + > + // > + // Step 1: Create HTTP request message with 4 headers: > + // > + HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || > + service->basicAuthStr) ? 8 : 7); if (HttpIoHeader == NULL) { > + goto ON_EXIT; > + } > + > + if(service->sessionToken) > + { > + Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service- > >sessionToken); > + ASSERT_EFI_ERROR (Status); > + } else if (service->basicAuthStr) { > + Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service- > >basicAuthStr); > + ASSERT_EFI_ERROR (Status); > + } > + > + if(contentType == NULL) { > + Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", > "application/json"); > + ASSERT_EFI_ERROR (Status); > + } else { > + Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", (CHAR8 *) > contentType); > + ASSERT_EFI_ERROR (Status); > + } > + Status = HttpIoSetHeader (HttpIoHeader, "Host", > + service->HostHeaderValue); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "Accept", "application/json"); > + ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader, > + "User-Agent", "libredfish"); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive"); > + ASSERT_EFI_ERROR (Status); AsciiSPrint( > + ContentLengthStr, > + sizeof (ContentLengthStr), > + "%lu", > + (UINT64) contentLength > + ); > + Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", > + ContentLengthStr); ASSERT_EFI_ERROR (Status); Status = > + HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0"); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Step 2: build the rest of HTTP request info. > + // > + RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA)); if > + (RequestData == NULL) { > + goto ON_EXIT; > + } > + > + RequestData->Method = HttpMethodPost; RequestData->Url = C8ToC16 > + (url); > + > + // > + // Step 3: fill in EFI_HTTP_MESSAGE > + // > + RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE)); if > + (RequestMsg == NULL) { > + goto ON_EXIT; > + } > + > + RequestMsg->Data.Request = RequestData; RequestMsg->HeaderCount > = > + HttpIoHeader->HeaderCount; > + RequestMsg->Headers = HttpIoHeader->Headers; > + RequestMsg->BodyLength = contentLength; > + RequestMsg->Body = (VOID*) content; > + > + ZeroMem (&ResponseMsg, sizeof (ResponseMsg)); > + > + // > + // Step 4: call RESTEx to get response from REST service. > + // > + Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, > + &ResponseMsg); if (EFI_ERROR (Status)) { > + goto ON_EXIT; > + } > + > + // > + // Step 5: Return the HTTP StatusCode and Body message. > + // > + if (ResponseMsg.Data.Response != NULL) { > + *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE)); > + if (*StatusCode == NULL) { > + goto ON_EXIT; > + } > + > + // > + // The caller shall take the responsibility to free the buffer. > + // > + **StatusCode = ResponseMsg.Data.Response->StatusCode; > + } > + > + if (ResponseMsg.Headers != NULL) { > + *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount); } > + > + if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) { > + ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, > + NULL); } > + > + // > + // Step 6: Parsing the HttpHeader to retrive the X-Auth-Token if the HTTP > StatusCode is correct. > + // > + if (ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_200_OK > || > + ResponseMsg.Data.Response->StatusCode == > HTTP_STATUS_204_NO_CONTENT) { > + HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount, > ResponseMsg.Headers, "X-Auth-Token"); > + if (HttpHeader != NULL) { > + if(service->sessionToken) > + { > + free(service->sessionToken); > + } > + service->sessionToken = AllocateCopyPool (AsciiStrSize (HttpHeader- > >FieldValue), HttpHeader->FieldValue); > + } > + > + /* > + // > + // Below opeation seems to be unnecessary. > + // Besides, the FieldValue for the Location is the full HTTP URI > (https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2F0.0.0 > .0%3A5000%2FXXX&data=05%7C01%7Cabner.chang%40amd.com%7C90 > 03fefe404646f2d91808da6f70b041%7C3dd8961fe4884e608e11a82d994e183d > %7C0%7C0%7C637944827040099707%7CUnknown%7CTWFpbGZsb3d8eyJWIj > oiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3 > 000%7C%7C%7C&sdata=tSmhlKBno3bHdyIGn2N5ESjfCdp%2FYUEYC%2F > Kqj9azORg%3D&reserved=0), so we can't use it as the > + // parameter of getUriFromService () directly. > + // > + HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount, > ResponseMsg.Headers, "Location"); > + if (HttpHeader != NULL) { > + ret = getUriFromService(service, HttpHeader->FieldValue); > + goto ON_EXIT; > + } > + */ > + } > + > +ON_EXIT: > + if (url != NULL) { > + free (url); > + } > + > + if (HttpIoHeader != NULL) { > + HttpIoFreeHeader (HttpIoHeader); > + } > + > + if (RequestData != NULL) { > + RestConfigFreeHttpRequestData (RequestData); } > + > + if (RequestMsg != NULL) { > + FreePool (RequestMsg); > + } > + > + RestConfigFreeHttpMessage (&ResponseMsg, FALSE); > + > + return ret; > +} > + > json_t* postUriFromService(redfishService* service, const char* uri, const > char* content, size_t contentLength, const char* contentType, > EFI_HTTP_STATUS_CODE** StatusCode) { > char* url = NULL; > -- > 2.32.0.windows.2 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#91916): https://edk2.groups.io/g/devel/message/91916 Mute This Topic: https://groups.io/mt/92641651/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-