如何在.NET Core中创建AWS Lambda的多部分响应?

huangapple go评论58阅读模式
英文:

AWS lambda how to create multipart response in .NET Core?

问题

I migrated an existing .NET Core service to AWS Lambda, and I am not sure how to send the correct multipart response from my function.cs.

原来的.NET Core服务返回了一个IActionResult并生成了一个多部分响应,包括第一部分的XML和第二部分的64位编码的HTML字符串。

我尝试了不同的返回类型,包括IActionResult,但都没有产生与原始REST服务相同的多部分输出。使用下面的代码,我的响应是:

{}

我该如何从function.cs返回以下结构?

多部分响应

--d3742228-85fc-4218-bf24-7e9dec746710
Content-Type: text/xml; charset=utf-8
Content-id: ACORD

<?xml version="1.0" encoding="utf-8"?>
<ACORD>
  <InsuranceSvcRs>
    <Status>
      <StatusCd>0</StatusCd>
      <StatusDesc>Success</StatusDesc>
    </Status>
  </InsuranceSvcRs>
</ACORD>
--d3742228-85fc-4218-bf24-7e9dec746710
Content-Type: application/html; charset=utf-8
Content-id: Inquiry.html
Content-description: Response to View Inquiry

PCFET0NUWVBFIEhUTUwgUFVCTElDICctLy9XM0MvL0RURC=
--d3742228-85fc-4218-bf24-7e9dec746710--

function.cs中的代码片段:

public async Task<IActionResult> FunctionHandler(ApiGatewayRequest.Root input, ILambdaContext context)
{
    IActionResult? ugResult = null;
    var result = controller.Post(apiGatewayRequest.body); //return multip-part response
    ugResult = result.GetAwaiter().GetResult(); 
    return ugResult;
}

原始REST控制器函数Post中的部分代码:

[HttpPost, Route("/api/Post")]
[Consumes("application/xml", "text/xml", "text/plain", "application/octet-stream", "application/json")]
public async Task<IActionResult> Post(string xmlfile)
{
    acordXml = await _gateway.ProcessIncomingRequestAndReturnXMLString(modifiedRequest, logTimeStamp);
    string htmlResponse = _gateway.CreateHtmlString(modifiedRequest, logTimeStamp);
    return new XmlAndEncodedHtmlMultipartResult().SetEncodedHtmlContent(htmlResponse).SetXmlContent(acordXml);
}

用于在REST中创建多部分响应的XmlAndEncodedHtmlMultipartResult类:

public class XmlAndEncodedHtmlMultipartResult : IActionResult
{
    private StringContent _xmlContent;
    private StringContent _htmlContent;
    public static string Subtype = "related";//my-xml+html
    private MultipartContent _multipartContent = new MultipartContent(Subtype); 

    public XmlAndEncodedHtmlMultipartResult SetXmlContent(string xml, string contentId = "ACORD")
    {
        var xmlContent = new StringContent(xml, Encoding.UTF8, "text/xml");
        xmlContent.Headers.Add("Content-id", contentId);
        this._xmlContent = xmlContent;
        return this;
    }

    public XmlAndEncodedHtmlMultipartResult SetEncodedHtmlContent(string rawHtml, string contentId = "Inquiry.html", string description = "Response to View Inquiry")
    {
        var bytes = Encoding.UTF8.GetBytes(rawHtml);
        var encodedHtml = Convert.ToBase64String(bytes);
        var htmlContent = new StringContent(encodedHtml, Encoding.UTF8, "application/html");
        htmlContent.Headers.Add("Content-id", contentId);
        htmlContent.Headers.Add("Content-description", description);
        this._htmlContent = htmlContent;
        return this;
    }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        this._multipartContent.Add(this._xmlContent);

        if(this._htmlContent != null)
            this._multipartContent.Add(this._htmlContent);

        var response = context.HttpContext.Response;
        response.ContentType = this._multipartContent.Headers.ContentType.ToString();
        await _multipartContent.CopyToAsync(response.Body);
    }
}

(Note: The code samples contain HTML-encoded characters. Please ensure that you handle these correctly when implementing the solution.)

英文:

I migrated an existing .NET Core service to AWS Lambda and I am not sure how to send the correct multipart response from my function.cs.

The original .NET Core service returned an IActionResult and produced a multipart response, consisting of a an XML for the first part, and a 64-bit encoded html string for the 2nd part.

I tried various return types including IActionResult and none of them produce the same multi-part output the original REST service did. Using the code below, my response is:

{}

How do I return the following structure from the function.cs?

Multipart response

--d3742228-85fc-4218-bf24-7e9dec746710
Content-Type: text/xml; charset=utf-8
Content-id: ACORD

<?xml version="1.0" encoding="utf-8"?>
<ACORD>
  <InsuranceSvcRs>
    <Status>
      <StatusCd>0</StatusCd>
      <StatusDesc>Success</StatusDesc>
    </Status>
  </InsuranceSvcRs>
</ACORD>
--d3742228-85fc-4218-bf24-7e9dec746710
Content-Type: application/html; charset=utf-8
Content-id: Inquiry.html
Content-description: Response to View Inquiry

PCFET0NUWVBFIEhUTUwgUFVCTElDICctLy9XM0MvL0RURC=
--d3742228-85fc-4218-bf24-7e9dec746710--

Code snippet from function.cs:

public async Task<IActionResult> FunctionHandler(ApiGatewayRequest.Root input, ILambdaContext context)
{
    IActionResult? ugResult = null;
    var result = controller.Post(apiGatewayRequest.body); //return multip-part response
    ugResult = result.GetAwaiter().GetResult(); 
    return ugResult;
}

Partial code inside original rest controller function named Post:

[HttpPost, Route("/api/Post")]
[Consumes("application/xml", "text/xml", "text/plain", "application/octet-stream", "application/json")]
public async Task<IActionResult> Post(string xmlfile)
{
    acordXml = await _gateway.ProcessIncomingRequestAndReturnXMLString(modifiedRequest, logTimeStamp);
    string htmlResponse = _gateway.CreateHtmlString(modifiedRequest, logTimeStamp);
    return new XmlAndEncodedHtmlMultipartResult().SetEncodedHtmlContent(htmlResponse).SetXmlContent(acordXml);
}

XmlAndEncodedHtmlMultipartResult class used to create multipart response in Rest:

public class XmlAndEncodedHtmlMultipartResult : IActionResult
{
    private StringContent _xmlContent;
    private StringContent _htmlContent;
    public static string Subtype = "related";//my-xml+html
    private MultipartContent _multipartContent = new MultipartContent(Subtype); 

    public XmlAndEncodedHtmlMultipartResult SetXmlContent(string xml, string contentId = "ACORD")
    {
        var xmlContent = new StringContent(xml, Encoding.UTF8, "text/xml");
        xmlContent.Headers.Add("Content-id", contentId);
        this._xmlContent = xmlContent;
        return this;
    }

    public XmlAndEncodedHtmlMultipartResult SetEncodedHtmlContent(string rawHtml, string contentId = "Inquiry.html", string description = "Response to View Inquiry")
    {
        var bytes = Encoding.UTF8.GetBytes(rawHtml);
        var encodedHtml = Convert.ToBase64String(bytes);
        var htmlContent = new StringContent(encodedHtml, Encoding.UTF8, "application/html");
        htmlContent.Headers.Add("Content-id", contentId);
        htmlContent.Headers.Add("Content-description", description);
        this._htmlContent = htmlContent;
        return this;
    }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        this._multipartContent.Add(this._xmlContent);

        if(this._htmlContent != null)
            this._multipartContent.Add(this._htmlContent);

        var response = context.HttpContext.Response;
        response.ContentType = this._multipartContent.Headers.ContentType.ToString();
        await _multipartContent.CopyToAsync(response.Body);
    }
}

答案1

得分: 2

不要回答我要翻译的问题。

以下是要翻译的内容:

"Instead of creating a stand-alone Lambda function that serves as a wrapper around the controller endpoint of interest -- you may have better luck instantiating/running your entire NET Core Web API project within a single Lambda function using the AWS provided NuGet package Amazon.Lambda.AspNetCoreServer and calling your existing endpoint of interest and examining the response."

"Updating an existing ASP.NET Core project to run in Lambda fronted by API Gateway is a very painless process and you should have greater parity with your application's HTTP responses instead of trying to mimic the server response with your Lambda function handler."

"References:
https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.AspNetCoreServer/README.md

https://aws.amazon.com/blogs/developer/running-serverless-asp-net-core-web-apis-with-amazon-lambda/"

英文:

Instead of creating a stand-alone Lambda function that serves as a wrapper around the controller endpoint of interest -- you may have better luck instantiating/running your entire NET Core Web API project within a single Lambda function using the AWS provided NuGet package Amazon.Lambda.AspNetCoreServer and calling your existing endpoint of interest and examining the response.

Updating an existing ASP.NET Core project to run in Lambda fronted by API Gateway is a very painless process and you should have greater parity with your application's HTTP responses instead of trying to mimic the server response with your Lambda function handler.

References:
https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.AspNetCoreServer/README.md

https://aws.amazon.com/blogs/developer/running-serverless-asp-net-core-web-apis-with-amazon-lambda/

huangapple
  • 本文由 发表于 2023年6月1日 11:07:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76378433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定