UEFI 应用程序:无法获取 Http GET 请求的正文

问题描述 投票:0回答:1

我正在使用 EDK2 环境开发 UEFI 应用程序,并尝试使用 UEFI API 执行 HTTP GET 请求。在 Http->Response 调用之后,该事件没有收到信号。如果我删除等待事件的部分,那么就会成功建立到服务器的连接,并且我能够毫无问题地接收 HTTP 响应标头。响应状态码为200 OK,表示请求成功。但在这种情况下身体仍然是空的。

  1. 我尝试引入延迟来等待响应正文被完全接收,但正文仍然是空的。
  2. 我尝试使用事件来处理响应,但它们没有收到信号。

如果您能提供有关如何解决此问题的任何见解或建议,我将不胜感激。我是否应该查看特定的 UEFI API 或步骤以确保我正确读取响应正文?任何帮助将不胜感激!

sendHttpRequest(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_STATUS Status;

    EFI_HTTP_PROTOCOL *Http;
    EFI_SERVICE_BINDING_PROTOCOL *HttpServiceBinding;
    EFI_HANDLE HttpHandle = NULL;
    EFI_HTTP_CONFIG_DATA HttpConfigData;
    EFI_HTTP_REQUEST_DATA RequestData;
    EFI_HTTP_RESPONSE_DATA ResponseData;
    EFI_HTTP_TOKEN RequestToken, ResponseToken;
    EFI_HTTP_MESSAGE RequestMessage, ResponseMessage;
    EFI_HTTP_HEADER Headers[2];
    CHAR16 *RequestUrl = L"http://" BOOT_SERVER_IP BOOT_CONFIG_PATH;
    CHAR8 *Buffer;
    BOOLEAN response_done;
    BOOLEAN request_done;
    UINTN Index;

    Print(L"Starting HttpBootClient default DHCP example\r\n");

    Status = gBS->LocateProtocol(&gEfiHttpServiceBindingProtocolGuid, NULL, (VOID **)&HttpServiceBinding);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to locate HTTP service binding protocol: %r\n", Status);
        return Status;
    }

    Status = HttpServiceBinding->CreateChild(HttpServiceBinding, &HttpHandle);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to create HTTP child: %r\n", Status);
        return Status;
    }

    Status = gBS->HandleProtocol(HttpHandle, &gEfiHttpProtocolGuid, (VOID **)&Http);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to locate HTTP protocol: %r\n", Status);
        return Status;
    }

    ZeroMem(&HttpConfigData, sizeof(HttpConfigData));
    HttpConfigData.HttpVersion = HttpVersion11;
    HttpConfigData.TimeOutMillisec = 500;
    HttpConfigData.LocalAddressIsIPv6 = FALSE;
    HttpConfigData.AccessPoint.IPv4Node = AllocatePool(sizeof(EFI_HTTPv4_ACCESS_POINT));
    if (!HttpConfigData.AccessPoint.IPv4Node)
    {
        Print(L"Failed to allocate memory for the structure\n");
        return EFI_OUT_OF_RESOURCES;
    }
    HttpConfigData.AccessPoint.IPv4Node->UseDefaultAddress = TRUE;

    Status = Http->Configure(Http, &HttpConfigData);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to configure HTTP protocol: %r\n", Status);
        return Status;
    }

    ZeroMem(&RequestData, sizeof(RequestData));
    RequestData.Method = HttpMethodGet;
    RequestData.Url = RequestUrl;

    ZeroMem(Headers, sizeof(Headers));
    Headers[0].FieldName = "Host";
    Headers[0].FieldValue = BOOT_SERVER_IP;
    Headers[1].FieldName = "User-Agent";
    Headers[1].FieldValue = "UEFI-Client";

    ZeroMem(&RequestMessage, sizeof(RequestMessage));
    RequestMessage.Data.Request = &RequestData;
    RequestMessage.Headers = Headers;
    RequestMessage.HeaderCount = 2;
    RequestMessage.BodyLength = 0;
    RequestMessage.Body = NULL;

    ZeroMem(&RequestToken, sizeof(RequestToken));
    RequestToken.Event = NULL;
    RequestToken.Message = &RequestMessage;

    request_done = FALSE;
    Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, httpnotify, &request_done, &RequestToken.Event);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to create request event: %r\n", Status);
        Http->Configure(Http, NULL);
        HttpServiceBinding->DestroyChild(HttpServiceBinding, HttpHandle);
        return Status;
    }
    else{
        Print(L"Event value : %p\n", RequestToken.Event);
    }

    Status = Http->Request(Http, &RequestToken);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to send HTTP request: %r\n", Status);
        Http->Configure(Http, NULL);
        HttpServiceBinding->DestroyChild(HttpServiceBinding, HttpHandle);
        return Status;
    }

    while (!request_done)
    {
        Status = Http->Poll(Http);
        Print(L"HTTP Poll: %r\n", Status);
    }
    Print(L"Request Sent : %r\n", Status);

    ZeroMem(&ResponseMessage, sizeof(ResponseMessage));
    ResponseData.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;
    ResponseMessage.Data.Response = &ResponseData;
    ResponseMessage.HeaderCount = 0;
    ResponseMessage.Headers = NULL;
    ResponseMessage.BodyLength = BUFFER_SIZE; 

    Status = gBS->AllocatePool(
        EfiBootServicesData,
        ResponseMessage.BodyLength,
        (VOID **)&Buffer);
    if (!Buffer)
    {
        Print(L"Failed to allocate memory for response body\n");
        Http->Configure(Http, NULL);
        HttpServiceBinding->DestroyChild(HttpServiceBinding, HttpHandle);
        return EFI_OUT_OF_RESOURCES;
    }
    ZeroMem(Buffer, sizeof(BUFFER_SIZE));
    ResponseMessage.Body = Buffer;

    ZeroMem(&ResponseToken, sizeof(ResponseToken));
    ResponseToken.Status = EFI_SUCCESS;
    ResponseToken.Message = &ResponseMessage;
    ResponseToken.Event = NULL;
    response_done = FALSE;
    Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, httpnotify, &response_done, &ResponseToken.Event);
    if (EFI_ERROR(Status))
    {
        Print(L"Failed to create response event: %r\n", Status);
        Http->Configure(Http, NULL);
        HttpServiceBinding->DestroyChild(HttpServiceBinding, HttpHandle);
        return Status;
    }
    else{
        Print(L"Event value : %p\n", ResponseToken.Event);
    }

    Status = Http->Response(Http, &ResponseToken);
    
    if (!EFI_ERROR(Status))
    {
        while (!response_done)
        {
            Status = Http->Poll(Http);
        }

        Print(L"HTTP response token: %r\n", ResponseToken.Status);

        Print(L"Status Code : %d\n", ResponseToken.Message->Data.Response->StatusCode);
        for (Index = 0; Index < ResponseMessage.HeaderCount; ++Index)
        {
            Print(L"%a: %a\n", ResponseMessage.Headers[Index].FieldName, ResponseMessage.Headers[Index].FieldValue);
        }

        if (ResponseMessage.Body && ResponseMessage.BodyLength > 0)
        {            
            Print(L"HTTP Response Body: %a\n", Buffer);
            Print(L"HTTP Response Body: %s\n", Buffer);
            Print(L"Body Length: %d\n", ResponseMessage.BodyLength);
        }
        else
        {
            Print(L"Response body is empty\n");
        }

    }
    else
    {
        Print(L"Failed to receive HTTP response: %r\n", Status);
    }

    if (Buffer)
    {
        FreePool(Buffer);
    }
    Http->Configure(Http, NULL);
    HttpServiceBinding->DestroyChild(HttpServiceBinding, HttpHandle);

    return EFI_SUCCESS;
}
http events https uefi get-request
1个回答
0
投票

服务器未发送“Content-Length”标头,这导致客户端无法确定何时终止请求。发送所需的标头后,问题就解决了。

© www.soinside.com 2019 - 2024. All rights reserved.