From: "Chang, Abner" <abner.chang@amd.com>
To: Nickle Wang <nickle.wang@hpe.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Yang, Atom" <Atom.Yang@amd.com>, Nick Ramirez <nramirez@nvidia.com>
Subject: Re: [edk2-staging][PATCH v3 09/15] edk2-staging/RedfishClientPkg: Update RedfishLib
Date: Thu, 28 Jul 2022 02:51:06 +0000 [thread overview]
Message-ID: <MN2PR12MB396616C8B4D56F72F807D5AAEA969@MN2PR12MB3966.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20220727013802.247-10-nickle.wang@hpe.com>
[AMD Official Use Only - General]
Reviewed-by: Abner Chang <abner.chang@amd.com>
> -----Original Message-----
> From: Nickle Wang <nickle.wang@hpe.com>
> Sent: Wednesday, July 27, 2022 9:38 AM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Yang, Atom
> <Atom.Yang@amd.com>; Nick Ramirez <nramirez@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.wang@hpe.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Yang Atom <Atom.Yang@amd.com>
> Cc: Nick Ramirez <nramirez@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
next prev parent reply other threads:[~2022-07-28 2:51 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-27 1:37 [edk2-staging][PATCH v3 00/15] Update RedfishClientpkg Nickle Wang
2022-07-27 1:37 ` [edk2-staging][PATCH v3 01/15] edk2-staging/RedfishClientPkg: Introduce Redfish event library Nickle Wang
2022-07-27 1:37 ` [edk2-staging][PATCH v3 02/15] edk2-staging/RedfishClientPkg: Introduce Redfish version library Nickle Wang
2022-07-27 1:37 ` [edk2-staging][PATCH v3 03/15] edk2-staging/RedfishClientPkg: Update Redfish Resource Config Protocol Nickle Wang
2022-07-27 1:37 ` [edk2-staging][PATCH v3 04/15] edk2-staging/RedfishClientPkg: Introduce Redfish resource config library Nickle Wang
2022-07-28 0:34 ` Chang, Abner
2022-07-27 1:37 ` [edk2-staging][PATCH v3 05/15] edk2-staging/RedfishClientPkg: Introduce resource identify library Nickle Wang
2022-07-27 15:48 ` Chang, Abner
2022-07-27 1:37 ` [edk2-staging][PATCH v3 06/15] edk2-staging/RedfishClientPkg: Introduce RedfishConfigLangMap driver Nickle Wang
2022-07-28 1:44 ` Chang, Abner
2022-07-27 1:37 ` [edk2-staging][PATCH v3 07/15] edk2-staging/RedfishClientPkg: Update ETag driver Nickle Wang
2022-07-28 1:45 ` Chang, Abner
2022-07-27 1:37 ` [edk2-staging][PATCH v3 08/15] edk2-staging/RedfishClientPkg: Update Redfish feature core driver Nickle Wang
2022-07-28 2:25 ` Chang, Abner
2022-07-27 1:37 ` [edk2-staging][PATCH v3 09/15] edk2-staging/RedfishClientPkg: Update RedfishLib Nickle Wang
2022-07-28 2:51 ` Chang, Abner [this message]
2022-07-27 1:37 ` [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: Update Redfish feature utility library Nickle Wang
2022-07-28 3:13 ` Chang, Abner
2022-07-28 3:14 ` Chang, Abner
2022-07-27 1:37 ` [edk2-staging][PATCH v3 11/15] edk2-staging/RedfishClientPkg: Rename RedfishMemoryCollection driver Nickle Wang
2022-07-28 3:41 ` Chang, Abner
2022-07-27 1:37 ` [edk2-staging][PATCH v3 12/15] edk2-staging/RedfishClientPkg: Rename Memory feature driver Nickle Wang
2022-07-28 3:43 ` Chang, Abner
2022-07-27 1:38 ` [edk2-staging][PATCH v3 13/15] edk2-staging/RedfishClientPkg: Introduce Computer System collection driver Nickle Wang
2022-07-28 3:46 ` Chang, Abner
2022-07-27 1:38 ` [edk2-staging][PATCH v3 14/15] edk2-staging/RedfishClientPkg: Introduce Computer System feature driver Nickle Wang
2022-07-28 3:48 ` Chang, Abner
2022-07-27 1:38 ` [edk2-staging][PATCH v3 15/15] edk2-staging/RedfishClientPkg: Introduce Bios " Nickle Wang
2022-07-28 3:48 ` Chang, Abner
2022-07-29 0:29 ` Nickle Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN2PR12MB396616C8B4D56F72F807D5AAEA969@MN2PR12MB3966.namprd12.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox