.NET Core 将本地 API 表单数据发布请求转发到远程 API [英] .NET Core forward a local API form-data post request to remote API

查看:69
本文介绍了.NET Core 将本地 API 表单数据发布请求转发到远程 API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 AJAX 表单,它将表单数据发布到本地 API url:/api/document.它包含一个文件和一个自定义 ID.我们只是想获取确切接收到的请求并将其转发到 example.com:8000/document/upload 上的远程 API.

是否有一种简单的方法可以使用 Asp.NET Core 将请求转发"(或代理?)到远程 API?

下面我们的想法是简单地使用 Web API Http 客户端来获取请求然后重新发送它(通过这样做我们希望能够例如从后端附加一个私有 api 密钥),但它似乎无法正常工作,PostAsync 不接受 Request.

Ajax 发送的原始请求

POST http://localhost:62640/api/document HTTP/1.1主机:本地主机:62640连接:保持连接内容长度:77424接受:应用程序/json缓存控制:无缓存用户代理:Mozilla/5.0(Windows NT 6.1;Win64;x64)AppleWebKit/537.36(KHTML,如 Gecko)Chrome/55.0.2883.87 Safari/537.36内容类型:多部分/表单数据;边界=----WebKitFormBoundaryn1BS5IFplQcUklyt接受编码:gzip、deflate、br接受语言:en-US,en;q=0.8,fr;q=0.6------WebKitFormBoundaryn1BS5IFplQcUklyt内容配置:表单数据;名称=文件上传";文件名=测试文档.pdf"内容类型:应用程序/pdf...------WebKitFormBoundaryn1BS5IFplQcUklyt内容配置:表单数据;名称=id"某某------WebKitFormBoundaryn1BS5IFplQcUklyt--

后端代码

我们的 .NET Core 后端有一个简单的转发到另一个 API"的目的.

公共类 DocumentUploadResult{公共 int 错误代码;公共字符串 docId;}[路由(api/[控制器]")]公共类 DocumentController :控制器{//POST api/文档[HttpPost]公共异步任务邮政(){client.BaseAddress = new Uri("http://example.com:8000");client.DefaultRequestHeaders.Accept.Clear();HttpResponseMessage response = await client.PostAsync("/document/upload", Request.Form);如果(响应.IsSuccessStatusCode){retValue = 等待 response.Content.ReadAsAsync();}返回值;}}

我们有一个 GET 请求(这里没有复制),它工作得很好.因为它不必从本地发布的数据中获取数据.

我的问题

如何简单地传递传入的本地 HttpPost 请求并将其转发到远程 API?

我在 stackoverflow 或网络上搜索了很多,但都是关于将 Request.Content 转发到远程的旧资源.

但是在 Asp.NET Core 1.0 上,我们无权访问 Content.我们只能检索 Request.Form(也不是 Request.Body),然后不接受它作为 PostAsync 方法的参数:<块引用>

无法从 Microsoft.AspNetCore.Http.IformCollection 转换为System.Net.Http.HttpContent

我的想法是直接将请求传递给 postAsync:

<块引用>

无法从 Microsoft.AspNetCore.Http.HttpRequest 转换为System.Net.Http.HttpContent

我不知道如何从我收到的本地请求中重建预期的 HttpContent.

预期响应

有关信息,当我们发布带有自定义 Id 和上传文件的有效表单数据时,远程 (example.com) API 响应为:

<代码>{错误代码":0"docId": "585846a1afe8ad12e46a4e60"}

解决方案

Ok 首先创建一个视图模型来保存表单信息.由于涉及文件上传,在模型中包含IFormFile.

公共类 FormData {公共 int id { 获取;放;}公共 IFormFile fileToUpload { 获取;放;}}

模型绑定器应该选择类型并用传入的数据填充模型.

更新控制器动作以接受模型并通过将内容复制到新请求来代理数据转发.

[Route("api/[controller]")]公共类文档控制器:控制器{//POST api/文档[HttpPost]公共异步任务Post(FormData formData) {if(formData != null && ModelState.IsValid) {client.BaseAddress = new Uri("http://example.com:8000");client.DefaultRequestHeaders.Accept.Clear();var multiContent = new MultipartFormDataContent();var file = formData.fileToUpload;如果(文件!= null){var fileStreamContent = new StreamContent(file.OpenReadStream());multiContent.Add(fileStreamContent, "fileToUpload", file.FileName);}multiContent.Add(new StringContent(formData.id.ToString()), "id");var response = await client.PostAsync("/document/upload", multiContent);如果(响应.IsSuccessStatusCode){var retValue = 等待 response.Content.ReadAsAsync();返回 Ok(reyValue);}}//如果我们得到了这么远的东西失败了.返回错误请求();}}

您可以根据需要包含必要的异常处理程序,但这是如何向前传递表单数据的最小示例.

I have an AJAX form which post a form-data to a local API url: /api/document. It contains a file and a custom Id. We simply want to take the exact received Request and forward it to a remote API at example.com:8000/document/upload.

Is there a simple way of achieve this "forward" (or proxy?) of the Request to a remote API using Asp.NET Core?

Below we had the idea to simply use Web API Http client to get the request and then resend it (by doing so we want to be able to for example append a private api key from the backend), but it seems not to work properly, the PostAsync doesn't accept the Request.

Raw request sent by Ajax

POST http://localhost:62640/api/document HTTP/1.1
Host: localhost:62640
Connection: keep-alive
Content-Length: 77424
Accept: application/json
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryn1BS5IFplQcUklyt
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8,fr;q=0.6

------WebKitFormBoundaryn1BS5IFplQcUklyt
Content-Disposition: form-data; name="fileToUpload"; filename="test-document.pdf"
Content-Type: application/pdf
...
------WebKitFormBoundaryn1BS5IFplQcUklyt
Content-Disposition: form-data; name="id"

someid
------WebKitFormBoundaryn1BS5IFplQcUklyt--

Backend Code

Our .NET Core backend has a simple "forward to another API" purpose.

public class DocumentUploadResult
{
     public int errorCode;
     public string docId;
}

[Route("api/[controller]")]
public class DocumentController : Controller
{
    // POST api/document
    [HttpPost]
    public async Task<DocumentUploadResult> Post()
    {
        client.BaseAddress = new Uri("http://example.com:8000");

        client.DefaultRequestHeaders.Accept.Clear();
        HttpResponseMessage response = await client.PostAsync("/document/upload", Request.Form);
        if (response.IsSuccessStatusCode)
        {
            retValue = await response.Content.ReadAsAsync<DocumentUploadResult>();
        }
        return retValue;
    }
}

We have a GET request (not reproduced here) which works just fine. As it doesn't have to fetch data from locally POSTed data.

My question

How to simply pass the incoming local HttpPost request and forwarding it to the remote API?

I searched A LOT on stackoverflow or on the web but all are old resources talking about forwarding Request.Content to the remote.

But on Asp.NET Core 1.0, we don't have access to Content. We only are able to retrieve Request.Form (nor Request.Body) which is then not accepted as an argument of PostAsync method:

Cannot convert from Microsoft.AspNetCore.Http.IformCollection to System.Net.Http.HttpContent

I had the idea to directly pass the request to the postAsync:

Cannot convert from Microsoft.AspNetCore.Http.HttpRequest to System.Net.Http.HttpContent

I don't know how to rebuild expected HttpContent from the local request I receive.

Expected response

For information, When we post a valid form-data with the custom Id and the uploaded file, the remote (example.com) API response is:

{
  "errorCode": 0
  "docId": "585846a1afe8ad12e46a4e60"
}

解决方案

Ok first create a view model to hold form information. Since file upload is involved, include IFormFile in the model.

public class FormData {
    public int id { get; set; }
    public IFormFile fileToUpload { get; set; }
}

The model binder should pick up the types and populate the model with the incoming data.

Update controller action to accept the model and proxy the data forward by copying content to new request.

[Route("api/[controller]")]
public class DocumentController : Controller {
    // POST api/document
    [HttpPost]
    public async Task<IActionResult> Post(FormData formData) {
        if(formData != null && ModelState.IsValid) {
            client.BaseAddress = new Uri("http://example.com:8000");
            client.DefaultRequestHeaders.Accept.Clear();

            var multiContent = new MultipartFormDataContent();

            var file = formData.fileToUpload;
            if(file != null) {
                var fileStreamContent = new StreamContent(file.OpenReadStream());
                multiContent.Add(fileStreamContent, "fileToUpload", file.FileName);
            }

            multiContent.Add(new StringContent(formData.id.ToString()), "id");

            var response = await client.PostAsync("/document/upload", multiContent);
            if (response.IsSuccessStatusCode) {
               var retValue = await response.Content.ReadAsAsync<DocumentUploadResult>();
               return Ok(reyValue);
            }
        }
        //if we get this far something Failed.
        return BadRequest();
    }        
}

You can include the necessary exception handlers as needed but this is a minimal example of how to pass the form data forward.

这篇关于.NET Core 将本地 API 表单数据发布请求转发到远程 API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆