VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/RedfishPkg/RedfishHttpDxe/RedfishHttpOperation.c@ 105670

最後變更 在這個檔案從105670是 105670,由 vboxsync 提交於 8 月 前

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 20.0 KB
 
1/** @file
2 RedfishHttpOperation handles HTTP operations.
3
4 Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include "RedfishHttpOperation.h"
11#include "RedfishHttpData.h"
12
13/**
14 This function copies all headers in SrcHeaders to DstHeaders.
15 It's call responsibility to release returned DstHeaders.
16
17 @param[in] SrcHeaders Source headers.
18 @param[in] SrcHeaderCount Number of header in source headers.
19 @param[out] DstHeaders Destination headers.
20 @param[out] DstHeaderCount Number of header in designation headers.
21
22 @retval EFI_SUCCESS Headers are copied successfully.
23 @retval Others Errors occur.
24
25**/
26EFI_STATUS
27CopyHttpHeaders (
28 IN EFI_HTTP_HEADER *SrcHeaders,
29 IN UINTN SrcHeaderCount,
30 OUT EFI_HTTP_HEADER **DstHeaders,
31 OUT UINTN *DstHeaderCount
32 )
33{
34 UINTN Index;
35
36 if ((SrcHeaders == NULL) || (SrcHeaderCount == 0) || (DstHeaders == NULL) || (DstHeaderCount == NULL)) {
37 return EFI_INVALID_PARAMETER;
38 }
39
40 *DstHeaderCount = 0;
41 *DstHeaders = AllocateZeroPool (sizeof (EFI_HTTP_HEADER) * SrcHeaderCount);
42 if (*DstHeaders == NULL) {
43 return EFI_OUT_OF_RESOURCES;
44 }
45
46 *DstHeaderCount = SrcHeaderCount;
47 for (Index = 0; Index < SrcHeaderCount; Index++) {
48 (*DstHeaders)[Index].FieldName = ASCII_STR_DUPLICATE (SrcHeaders[Index].FieldName);
49 if ((*DstHeaders)[Index].FieldName == NULL) {
50 return EFI_OUT_OF_RESOURCES;
51 }
52
53 (*DstHeaders)[Index].FieldValue = ASCII_STR_DUPLICATE (SrcHeaders[Index].FieldValue);
54 if ((*DstHeaders)[Index].FieldValue == NULL) {
55 return EFI_OUT_OF_RESOURCES;
56 }
57 }
58
59 return EFI_SUCCESS;
60}
61
62/**
63 This function free resources in Request. Request is no longer available
64 after this function returns successfully.
65
66 @param[in] Request HTTP request to be released.
67
68 @retval EFI_SUCCESS Resource is released successfully.
69 @retval Others Errors occur.
70
71**/
72EFI_STATUS
73ReleaseRedfishRequest (
74 IN REDFISH_REQUEST *Request
75 )
76{
77 if (Request == NULL) {
78 return EFI_INVALID_PARAMETER;
79 }
80
81 if ((Request->Headers != NULL) && (Request->HeaderCount > 0)) {
82 HttpFreeHeaderFields (Request->Headers, Request->HeaderCount);
83 Request->Headers = NULL;
84 Request->HeaderCount = 0;
85 }
86
87 if (Request->Content != NULL) {
88 FreePool (Request->Content);
89 Request->Content = NULL;
90 }
91
92 if (Request->ContentType != NULL) {
93 FreePool (Request->ContentType);
94 Request->ContentType = NULL;
95 }
96
97 Request->ContentLength = 0;
98
99 return EFI_SUCCESS;
100}
101
102/**
103 This function free resources in given Response.
104
105 @param[in] Response HTTP response to be released.
106
107 @retval EFI_SUCCESS Resource is released successfully.
108 @retval Others Errors occur.
109
110**/
111EFI_STATUS
112ReleaseRedfishResponse (
113 IN REDFISH_RESPONSE *Response
114 )
115{
116 if (Response == NULL) {
117 return EFI_INVALID_PARAMETER;
118 }
119
120 if ((Response->Headers != NULL) && (Response->HeaderCount > 0)) {
121 HttpFreeHeaderFields (Response->Headers, Response->HeaderCount);
122 Response->Headers = NULL;
123 Response->HeaderCount = 0;
124 }
125
126 if (Response->Payload != NULL) {
127 ReleaseRedfishPayload (Response->Payload);
128 Response->Payload = NULL;
129 }
130
131 if (Response->StatusCode != NULL) {
132 FreePool (Response->StatusCode);
133 Response->StatusCode = NULL;
134 }
135
136 return EFI_SUCCESS;
137}
138
139/**
140 This function free resources in given HTTP message.
141
142 @param[in] HttpMessage HTTP message to be released.
143 @param[in] IsRequest TRUE if this is request type of HTTP message.
144 FALSE if this is response type of HTTP message.
145
146 @retval EFI_SUCCESS Resource is released successfully.
147 @retval Others Errors occur.
148
149**/
150EFI_STATUS
151ReleaseHttpMessage (
152 IN EFI_HTTP_MESSAGE *HttpMessage,
153 IN BOOLEAN IsRequest
154 )
155{
156 if (HttpMessage == NULL) {
157 return EFI_INVALID_PARAMETER;
158 }
159
160 if (IsRequest) {
161 if (HttpMessage->Data.Request != NULL) {
162 if (HttpMessage->Data.Request->Url != NULL) {
163 FreePool (HttpMessage->Data.Request->Url);
164 }
165
166 FreePool (HttpMessage->Data.Request);
167 HttpMessage->Data.Request = NULL;
168 }
169 } else {
170 if (HttpMessage->Data.Response != NULL) {
171 FreePool (HttpMessage->Data.Response);
172 HttpMessage->Data.Response = NULL;
173 }
174 }
175
176 if (HttpMessage->Body != NULL) {
177 FreePool (HttpMessage->Body);
178 HttpMessage->Body = NULL;
179 }
180
181 if (HttpMessage->Headers != NULL) {
182 HttpFreeHeaderFields (HttpMessage->Headers, HttpMessage->HeaderCount);
183 HttpMessage->Headers = NULL;
184 HttpMessage->HeaderCount = 0;
185 }
186
187 return EFI_SUCCESS;
188}
189
190/**
191 This function build Redfish message for sending data to Redfish service.
192 It's call responsibility to properly release returned HTTP message by
193 calling ReleaseHttpMessage.
194
195 @param[in] ServicePrivate Pointer to Redfish service private data.
196 @param[in] Uri Redfish service URI.
197 @param[in] Method HTTP method.
198 @param[in] Request Additional data to send to Redfish service.
199 This is optional.
200 @param[in] ContentEncoding Content encoding method to compress HTTP context.
201 This is optional. When ContentEncoding is NULL,
202 No compress method will be performed.
203
204 @retval EFI_HTTP_MESSAGE * Pointer to newly created HTTP message.
205 @retval NULL Error occurred.
206
207**/
208EFI_HTTP_MESSAGE *
209BuildRequestMessage (
210 IN REDFISH_SERVICE_PRIVATE *ServicePrivate,
211 IN EFI_STRING Uri,
212 IN EFI_HTTP_METHOD Method,
213 IN REDFISH_REQUEST *Request OPTIONAL,
214 IN CHAR8 *ContentEncoding OPTIONAL
215 )
216{
217 EFI_STATUS Status;
218 EFI_STRING Url;
219 UINTN UrlSize;
220 UINTN Index;
221 EFI_HTTP_MESSAGE *RequestMsg;
222 EFI_HTTP_REQUEST_DATA *RequestData;
223 UINTN HeaderCount;
224 UINTN HeaderIndex;
225 EFI_HTTP_HEADER *Headers;
226 CHAR8 ContentLengthStr[REDFISH_CONTENT_LENGTH_SIZE];
227 VOID *Content;
228 UINTN ContentLength;
229 BOOLEAN HasContent;
230 BOOLEAN DoContentEncoding;
231
232 RequestMsg = NULL;
233 RequestData = NULL;
234 Url = NULL;
235 UrlSize = 0;
236 Content = NULL;
237 ContentLength = 0;
238 HeaderCount = REDFISH_COMMON_HEADER_SIZE;
239 HeaderIndex = 0;
240 Headers = NULL;
241 HasContent = FALSE;
242 DoContentEncoding = FALSE;
243
244 if ((ServicePrivate == NULL) || (IS_EMPTY_STRING (Uri))) {
245 return NULL;
246 }
247
248 if (Method >= HttpMethodMax) {
249 return NULL;
250 }
251
252 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: %s\n", __func__, Uri));
253
254 //
255 // Build full URL for HTTP query.
256 //
257 UrlSize = (AsciiStrLen (ServicePrivate->Host) + StrLen (Uri) + 1) * sizeof (CHAR16);
258 Url = AllocateZeroPool (UrlSize);
259 if (Url == NULL) {
260 return NULL;
261 }
262
263 UnicodeSPrint (Url, UrlSize, L"%a%s", ServicePrivate->Host, Uri);
264 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: Url: %s\n", __func__, Url));
265
266 //
267 // Step 1: build the HTTP headers.
268 //
269 if (!IS_EMPTY_STRING (ServicePrivate->SessionToken) || !IS_EMPTY_STRING (ServicePrivate->BasicAuth)) {
270 HeaderCount++;
271 }
272
273 if ((Request != NULL) && (Request->HeaderCount > 0)) {
274 HeaderCount += Request->HeaderCount;
275 }
276
277 //
278 // Check and see if we will do content encoding or not
279 //
280 if (!IS_EMPTY_STRING (ContentEncoding)) {
281 if (AsciiStrCmp (ContentEncoding, REDFISH_HTTP_CONTENT_ENCODING_NONE) != 0) {
282 DoContentEncoding = TRUE;
283 }
284 }
285
286 if ((Request != NULL) && !IS_EMPTY_STRING (Request->Content)) {
287 HeaderCount += 2;
288 HasContent = TRUE;
289 if (DoContentEncoding) {
290 HeaderCount += 1;
291 }
292 }
293
294 Headers = AllocateZeroPool (HeaderCount * sizeof (EFI_HTTP_HEADER));
295 if (Headers == NULL) {
296 goto ON_ERROR;
297 }
298
299 if (!IS_EMPTY_STRING (ServicePrivate->SessionToken)) {
300 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_X_AUTH_TOKEN, ServicePrivate->SessionToken);
301 if (EFI_ERROR (Status)) {
302 goto ON_ERROR;
303 }
304 } else if (!IS_EMPTY_STRING (ServicePrivate->BasicAuth)) {
305 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_AUTHORIZATION, ServicePrivate->BasicAuth);
306 if (EFI_ERROR (Status)) {
307 goto ON_ERROR;
308 }
309 }
310
311 if (Request != NULL) {
312 for (Index = 0; Index < Request->HeaderCount; Index++) {
313 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], Request->Headers[Index].FieldName, Request->Headers[Index].FieldValue);
314 if (EFI_ERROR (Status)) {
315 goto ON_ERROR;
316 }
317 }
318 }
319
320 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_HOST, ServicePrivate->HostName);
321 if (EFI_ERROR (Status)) {
322 goto ON_ERROR;
323 }
324
325 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], REDFISH_HTTP_HEADER_ODATA_VERSION_STR, REDFISH_HTTP_HEADER_ODATA_VERSION_VALUE);
326 if (EFI_ERROR (Status)) {
327 goto ON_ERROR;
328 }
329
330 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_ACCEPT, HTTP_CONTENT_TYPE_APP_JSON);
331 if (EFI_ERROR (Status)) {
332 goto ON_ERROR;
333 }
334
335 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_USER_AGENT, REDFISH_HTTP_HEADER_USER_AGENT_VALUE);
336 if (EFI_ERROR (Status)) {
337 goto ON_ERROR;
338 }
339
340 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], REDFISH_HTTP_HEADER_CONNECTION_STR, REDFISH_HTTP_HEADER_CONNECTION_VALUE);
341 if (EFI_ERROR (Status)) {
342 goto ON_ERROR;
343 }
344
345 //
346 // Handle content header
347 //
348 if (HasContent) {
349 if (Request->ContentType == NULL) {
350 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TYPE_APP_JSON);
351 if (EFI_ERROR (Status)) {
352 goto ON_ERROR;
353 }
354 } else {
355 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_CONTENT_TYPE, Request->ContentType);
356 if (EFI_ERROR (Status)) {
357 goto ON_ERROR;
358 }
359 }
360
361 if (Request->ContentLength == 0) {
362 Request->ContentLength = AsciiStrLen (Request->Content);
363 }
364
365 AsciiSPrint (
366 ContentLengthStr,
367 sizeof (ContentLengthStr),
368 "%lu",
369 (UINT64)Request->ContentLength
370 );
371 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_CONTENT_LENGTH, ContentLengthStr);
372 if (EFI_ERROR (Status)) {
373 goto ON_ERROR;
374 }
375
376 //
377 // Encoding
378 //
379 if (DoContentEncoding) {
380 //
381 // We currently only support gzip Content-Encoding.
382 //
383 Status = RedfishContentEncode (
384 ContentEncoding,
385 Request->Content,
386 Request->ContentLength,
387 &Content,
388 &ContentLength
389 );
390 if (Status == EFI_INVALID_PARAMETER) {
391 DEBUG ((DEBUG_ERROR, "%a: Error to encode content.\n", __func__));
392 goto ON_ERROR;
393 } else if (Status == EFI_UNSUPPORTED) {
394 DoContentEncoding = FALSE;
395 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: No content coding for %a! Use raw data instead.\n", __func__, ContentEncoding));
396 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_CONTENT_ENCODING, HTTP_CONTENT_ENCODING_IDENTITY);
397 if (EFI_ERROR (Status)) {
398 goto ON_ERROR;
399 }
400 } else {
401 Status = HttpSetFieldNameAndValue (&Headers[HeaderIndex++], HTTP_HEADER_CONTENT_ENCODING, HTTP_CONTENT_ENCODING_GZIP);
402 if (EFI_ERROR (Status)) {
403 goto ON_ERROR;
404 }
405 }
406 }
407
408 //
409 // When the content is from caller, we use our own copy so that we properly release it later.
410 //
411 if (!DoContentEncoding) {
412 Content = AllocateCopyPool (Request->ContentLength, Request->Content);
413 if (Content == NULL) {
414 goto ON_ERROR;
415 }
416
417 ContentLength = Request->ContentLength;
418 }
419 }
420
421 //
422 // Step 2: build the rest of HTTP request info.
423 //
424 RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));
425 if (RequestData == NULL) {
426 goto ON_ERROR;
427 }
428
429 RequestData->Method = Method;
430 RequestData->Url = Url;
431
432 //
433 // Step 3: fill in EFI_HTTP_MESSAGE
434 //
435 RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));
436 if (RequestMsg == NULL) {
437 goto ON_ERROR;
438 }
439
440 ASSERT (HeaderIndex == HeaderCount);
441 RequestMsg->Data.Request = RequestData;
442 RequestMsg->HeaderCount = HeaderIndex;
443 RequestMsg->Headers = Headers;
444
445 if (HasContent) {
446 RequestMsg->BodyLength = ContentLength;
447 RequestMsg->Body = Content;
448 }
449
450 return RequestMsg;
451
452ON_ERROR:
453
454 if (Headers != NULL) {
455 HttpFreeHeaderFields (Headers, HeaderIndex);
456 }
457
458 if (RequestData != NULL) {
459 FreePool (RequestData);
460 }
461
462 if (RequestMsg != NULL) {
463 FreePool (RequestMsg);
464 }
465
466 if (Url != NULL) {
467 FreePool (Url);
468 }
469
470 return NULL;
471}
472
473/**
474 This function parse response message from Redfish service, and
475 build Redfish response for caller. It's call responsibility to
476 properly release Redfish response by calling ReleaseRedfishResponse.
477
478 @param[in] ServicePrivate Pointer to Redfish service private data.
479 @param[in] ResponseMsg Response message from Redfish service.
480 @param[out] RedfishResponse Redfish response data.
481
482 @retval EFI_SUCCESS Redfish response is returned successfully.
483 @retval Others Errors occur.
484
485**/
486EFI_STATUS
487ParseResponseMessage (
488 IN REDFISH_SERVICE_PRIVATE *ServicePrivate,
489 IN EFI_HTTP_MESSAGE *ResponseMsg,
490 OUT REDFISH_RESPONSE *RedfishResponse
491 )
492{
493 EFI_STATUS Status;
494 EDKII_JSON_VALUE JsonData;
495 EFI_HTTP_HEADER *ContentEncodedHeader;
496 VOID *DecodedBody;
497 UINTN DecodedLength;
498
499 if ((ServicePrivate == NULL) || (ResponseMsg == NULL) || (RedfishResponse == NULL)) {
500 return EFI_INVALID_PARAMETER;
501 }
502
503 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a\n", __func__));
504
505 //
506 // Initialization
507 //
508 JsonData = NULL;
509 RedfishResponse->HeaderCount = 0;
510 RedfishResponse->Headers = NULL;
511 RedfishResponse->Payload = NULL;
512 RedfishResponse->StatusCode = NULL;
513 DecodedBody = NULL;
514 DecodedLength = 0;
515
516 //
517 // Return the HTTP StatusCode.
518 //
519 if (ResponseMsg->Data.Response != NULL) {
520 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: status: %d\n", __func__, ResponseMsg->Data.Response->StatusCode));
521 RedfishResponse->StatusCode = AllocateCopyPool (sizeof (EFI_HTTP_STATUS_CODE), &ResponseMsg->Data.Response->StatusCode);
522 if (RedfishResponse->StatusCode == NULL) {
523 DEBUG ((DEBUG_ERROR, "%a: Failed to create status code.\n", __func__));
524 }
525 }
526
527 //
528 // Return the HTTP headers.
529 //
530 if (ResponseMsg->Headers != NULL) {
531 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: header count: %d\n", __func__, ResponseMsg->HeaderCount));
532 Status = CopyHttpHeaders (
533 ResponseMsg->Headers,
534 ResponseMsg->HeaderCount,
535 &RedfishResponse->Headers,
536 &RedfishResponse->HeaderCount
537 );
538 if (EFI_ERROR (Status)) {
539 DEBUG ((DEBUG_ERROR, "%a: Failed to copy HTTP headers: %r\n", __func__, Status));
540 }
541 }
542
543 //
544 // Return the HTTP body.
545 //
546 if ((ResponseMsg->BodyLength != 0) && (ResponseMsg->Body != NULL)) {
547 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: body length: %d\n", __func__, ResponseMsg->BodyLength));
548 //
549 // Check if data is encoded.
550 //
551 ContentEncodedHeader = HttpFindHeader (RedfishResponse->HeaderCount, RedfishResponse->Headers, HTTP_HEADER_CONTENT_ENCODING);
552 if (ContentEncodedHeader != NULL) {
553 //
554 // The content is encoded.
555 //
556 Status = RedfishContentDecode (
557 ContentEncodedHeader->FieldValue,
558 ResponseMsg->Body,
559 ResponseMsg->BodyLength,
560 &DecodedBody,
561 &DecodedLength
562 );
563 if (EFI_ERROR (Status)) {
564 DEBUG ((DEBUG_ERROR, "%a: Failed to decompress the response content: %r decoding method: %a\n.", __func__, Status, ContentEncodedHeader->FieldValue));
565 goto ON_ERROR;
566 }
567
568 JsonData = JsonLoadBuffer (DecodedBody, DecodedLength, 0, NULL);
569 FreePool (DecodedBody);
570 } else {
571 JsonData = JsonLoadBuffer (ResponseMsg->Body, ResponseMsg->BodyLength, 0, NULL);
572 }
573
574 if (!JsonValueIsNull (JsonData)) {
575 RedfishResponse->Payload = CreateRedfishPayload (ServicePrivate, JsonData);
576 if (RedfishResponse->Payload == NULL) {
577 DEBUG ((DEBUG_ERROR, "%a: Failed to create payload\n.", __func__));
578 }
579
580 JsonValueFree (JsonData);
581 } else {
582 DEBUG ((DEBUG_ERROR, "%a: No payload available\n", __func__));
583 }
584 }
585
586 return EFI_SUCCESS;
587
588ON_ERROR:
589
590 if (RedfishResponse != NULL) {
591 ReleaseRedfishResponse (RedfishResponse);
592 }
593
594 return Status;
595}
596
597/**
598 This function send Redfish request to Redfish service by calling
599 Rest Ex protocol.
600
601 @param[in] Service Pointer to Redfish service.
602 @param[in] Uri Uri of Redfish service.
603 @param[in] Method HTTP method.
604 @param[in] Request Request data. This is optional.
605 @param[out] Response Redfish response data.
606
607 @retval EFI_SUCCESS Request is sent and received successfully.
608 @retval Others Errors occur.
609
610**/
611EFI_STATUS
612HttpSendReceive (
613 IN REDFISH_SERVICE Service,
614 IN EFI_STRING Uri,
615 IN EFI_HTTP_METHOD Method,
616 IN REDFISH_REQUEST *Request OPTIONAL,
617 OUT REDFISH_RESPONSE *Response
618 )
619{
620 EFI_STATUS Status;
621 EFI_STATUS RestExStatus;
622 EFI_HTTP_MESSAGE *RequestMsg;
623 EFI_HTTP_MESSAGE ResponseMsg;
624 REDFISH_SERVICE_PRIVATE *ServicePrivate;
625 EFI_HTTP_HEADER *XAuthTokenHeader;
626 CHAR8 *HttpContentEncoding;
627
628 if ((Service == NULL) || IS_EMPTY_STRING (Uri) || (Response == NULL)) {
629 return EFI_INVALID_PARAMETER;
630 }
631
632 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: Method: 0x%x %s\n", __func__, Method, Uri));
633
634 ServicePrivate = (REDFISH_SERVICE_PRIVATE *)Service;
635 if (ServicePrivate->Signature != REDFISH_HTTP_SERVICE_SIGNATURE) {
636 DEBUG ((DEBUG_ERROR, "%a: signature check failure\n", __func__));
637 return EFI_INVALID_PARAMETER;
638 }
639
640 ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
641 HttpContentEncoding = (CHAR8 *)PcdGetPtr (PcdRedfishServiceContentEncoding);
642
643 RequestMsg = BuildRequestMessage (Service, Uri, Method, Request, HttpContentEncoding);
644 if (RequestMsg == NULL) {
645 DEBUG ((DEBUG_ERROR, "%a: cannot build request message for %s\n", __func__, Uri));
646 return EFI_PROTOCOL_ERROR;
647 }
648
649 //
650 // call RESTEx to get response from REST service.
651 //
652 RestExStatus = ServicePrivate->RestEx->SendReceive (ServicePrivate->RestEx, RequestMsg, &ResponseMsg);
653 if (EFI_ERROR (RestExStatus)) {
654 DEBUG ((DEBUG_ERROR, "%a: %s SendReceive failure: %r\n", __func__, Uri, RestExStatus));
655 }
656
657 //
658 // Return status code, headers and payload to caller as much as possible even when RestEx returns failure.
659 //
660 Status = ParseResponseMessage (ServicePrivate, &ResponseMsg, Response);
661 if (EFI_ERROR (Status)) {
662 DEBUG ((DEBUG_ERROR, "%a: %s parse response failure: %r\n", __func__, Uri, Status));
663 } else {
664 //
665 // Capture session token in header
666 //
667 if ((Method == HttpMethodPost) &&
668 (Response->StatusCode != NULL) &&
669 ((*Response->StatusCode == HTTP_STATUS_200_OK) || (*Response->StatusCode == HTTP_STATUS_204_NO_CONTENT)))
670 {
671 XAuthTokenHeader = HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.Headers, HTTP_HEADER_X_AUTH_TOKEN);
672 if (XAuthTokenHeader != NULL) {
673 Status = UpdateSessionToken (ServicePrivate, XAuthTokenHeader->FieldValue);
674 if (EFI_ERROR (Status)) {
675 DEBUG ((DEBUG_ERROR, "%a: update session token failure: %r\n", __func__, Status));
676 }
677 }
678 }
679 }
680
681 //
682 // Release resources
683 //
684 if (RequestMsg != NULL) {
685 ReleaseHttpMessage (RequestMsg, TRUE);
686 FreePool (RequestMsg);
687 }
688
689 ReleaseHttpMessage (&ResponseMsg, FALSE);
690
691 return RestExStatus;
692}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette