创建包含多个 HTTP 请求的 mime/multipart 请求

2024-01-12

我正在关注this http://blogs.msdn.com/b/webdev/archive/2013/11/01/introducing-batch-support-in-web-api-and-web-api-odata.aspx使用 ASP.NET 4.5 批处理 http 请求的教程。我有sample http://aspnet.codeplex.com/sourcecontrol/latest#Samples/WebApi/BatchSample/ReadMe.txt正在工作,现在我需要用 Python 编写一个客户端应用程序。

此代码创建批量请求并将其发送到 Web API:

JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
//Create a request to query for customers
HttpRequestMessage queryCustomersRequest = new HttpRequestMessage(HttpMethod.Get, serviceUrl + "/Customers");
//Create a message to add a customer
HttpRequestMessage addCustomerRequest = new HttpRequestMessage(HttpMethod.Post, serviceUrl + "/Customers");
addCustomerRequest.Content = new ObjectContent<Customer>(addedCustomer, formatter);
//Create a message to update a customer
HttpRequestMessage updateCustomerRequest = new HttpRequestMessage(HttpMethod.Put, string.Format(serviceUrl + "/Customers/{0}", updatedCustomer.Id));
updateCustomerRequest.Content = new ObjectContent<Customer>(updatedCustomer, formatter);
//Create a message to remove a customer.
HttpRequestMessage removeCustomerRequest = new HttpRequestMessage(HttpMethod.Delete, string.Format(serviceUrl + "/Customers/{0}", removedCustomer.Id));

//Create the different parts of the multipart content
HttpMessageContent queryContent = new HttpMessageContent(queryCustomersRequest);
HttpMessageContent addCustomerContent = new HttpMessageContent(addCustomerRequest);
HttpMessageContent updateCustomerContent = new HttpMessageContent(updateCustomerRequest);
HttpMessageContent removeCustomerContent = new HttpMessageContent(removeCustomerRequest);

//Create the multipart/mixed message content
MultipartContent content = new MultipartContent("mixed", "batch_" + Guid.NewGuid().ToString());
content.Add(queryContent);
content.Add(addCustomerContent);
content.Add(updateCustomerContent);
content.Add(removeCustomerContent);

//Create the request to the batch service
HttpRequestMessage batchRequest = new HttpRequestMessage(HttpMethod.Post, serviceUrl + "/batch");
//Associate the content with the message
batchRequest.Content = content;

//Send the message
HttpResponseMessage batchResponse = await client.SendAsync(batchRequest);

这是我在 Python 中的尝试,但它不起作用:

def build_request( url, type, headers, data = {}):

    #Build appropriate request
    if type == "get":
        request = Request('GET', url, headers=headers)

    elif type == "post":
        request = Request('POST', url, data = json.dumps(data), headers = {'Content-Type':'application/json'})

    elif type == "delete":
        request = Request('DELETE', url, headers = {'Content-Type':'application/json'})

    elif type == "put":
        request = Request('PUT', url, data = json.dumps(data), headers = {'Content-Type':'application/json'})

    elif type == "patch":
        request = Request('PATCH', url, data = json.dumps(data), headers = {'Content-Type':'application/json'})

    prepared_request = request.prepare()
    return prepared_request



#Get customers
get_customers = build_request( url + "/Customers", "get", headers)

#Add a customer
add_customer = build_request( url + "/Customers", "post", data=added_customer, headers=headers)

#update a customer
update_customer = build_request( url + "/Customers/{0}".format(updated_customer["Id"]), "put", data=updated_customer, headers=headers)

#Remove a customer
remove_customer = build_request( url + "/Customers/{0}".format(removed_customer["Id"]), "delete", headers=headers)

request_list = [get_customers,add_customer,update_customer, remove_customer]

batch_request = requests.Request('POST',url + "/batch", data=request_list)

s = Session()

batch_request.prepare()

resp = s.send(batch_request)

该请求应如下所示:

POST http://localhost:12345/api/batch HTTP/1.1
Content-Type: multipart/mixed; boundary="batch_357647d1-a6b5-4e6a-aa73-edfc88d8866e"
Host: localhost:12345
Content-Length: 857
Expect: 100-continue

--batch_357647d1-a6b5-4e6a-aa73-edfc88d8866e
Content-Type: application/http; msgtype=request

GET /api/WebCustomers HTTP/1.1
Host: localhost:13245


--batch_357647d1-a6b5-4e6a-aa73-edfc88d8866e
Content-Type: application/http; msgtype=request

POST /api/WebCustomers HTTP/1.1
Host: localhost:13245
Content-Type: application/json; charset=utf-8

{"Id":129,"Name":"Name4752cbf0-e365-43c3-aa8d-1bbc8429dbf8"}
--batch_357647d1-a6b5-4e6a-aa73-edfc88d8866e
Content-Type: application/http; msgtype=request

PUT /api/WebCustomers/1 HTTP/1.1
Host: localhost:13245
Content-Type: application/json; charset=utf-8

{"Id":1,"Name":"Peter"}
--batch_357647d1-a6b5-4e6a-aa73-edfc88d8866e
Content-Type: application/http; msgtype=request

DELETE /api/WebCustomers/2 HTTP/1.1
Host: localhost:13245


--batch_357647d1-a6b5-4e6a-aa73-edfc88d8866e--

我已成功使用以下代码将 C# 示例的第一部分转换为 Python:

class BatchRequest:
    'Class for sending several HTTP requests in a single request'

    def __init__(self, url, uuid):
        self.batch_url = batch_url
        self.uuid = uuid
        self.data = ""
        self.headers = {"Content-Type" : "multipart/mixed; boundary=\"batch_{0}\"".format(uuid)}

    #Build sub-request depending on Method and Data supplied 
    def add_request(self, method, url, data={}):

        if method == "GET":
            self.data += "--batch_{0}\r\nContent-Type: application/http; msgtype=request\r\n\r\n{1} {2} HTTP/1.1\r\nHost: localhost:65200\r\n\r\n\r\n".format(uuid, method, url)

        #If no data, have alternative option
        elif method == "POST" or method == "PUT":
            self.data += "--batch_{0}\r\nContent-Type: application/http; msgtype=request\r\n\r\n{1} {2} HTTP/1.1\r\nHost: localhost:65200\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{3}\r\n".format(uuid, method, url, json.dumps(data))

        elif method == "DELETE":
            self.data += "--batch_{0}\r\nContent-Type: application/http; msgtype=request\r\n\r\n{1} {2} HTTP/1.1\r\nHost: localhost:65200\r\n\r\n\r\n".format(uuid, method, url)

    def execute_request(self):
        #Add the "closing" boundary  
        self.data += "--batch_{0}--\r\n".format(uuid)

        result = requests.post(self.batch_url, data=self.data, headers=self.headers)
        return result

if __name__ == '__main__':

    url = "http://localhost:65200/api"

    batch_url = "{0}/batch".format(url)

    uuid = uuid.uuid4()

    br = BatchRequest("http://localhost:65200/api", uuid)

    #Get customers
    br.add_request("GET", "/api/Customers")

    #Create a new customer
    new_customer = {"Id" : 10, "Name" : "Name 10"};
    br.add_request("POST", "/api/Customers", new_customer)

    #Update the name of the first customer in the list 
    update_customer = customer_list[0]
    update_customer["Name"] = "Peter"
    br.add_request("PUT", "/api/Customers/{0}".format(update_customer["Id"]), update_customer)

    #Remove the second customer in the list
    br.add_request("DELETE", "/api/Customers/{0}".format(customer_list[1]["Id"]))

    result = br.execute_request()

剩下的就是弄清楚如何解析来自服务器的响应。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建包含多个 HTTP 请求的 mime/multipart 请求 的相关文章

随机推荐

  • 如何为超类编写 Hibernate Criteria 查询并检查某个子类?

    如何为超类编写 Hibernate Criteria 查询并检查某个子类 假设我们有以下所有类都与 Hibernate JPA 映射 Entity Inheritance strategy InheritanceType JOINED pu
  • 为什么我无法在 Swift iOS 应用程序中使用 CIFilter 将图像反转回原始图像

    我正在开发一个简单的应用程序 它有一个带有预加载图像和按钮的图像视图 按下按钮时 图像视图中的图像应反转 它第一次工作 但我希望当我再次按下按钮时它会将图像反转回其原始形式 然而 第二次按下按钮时它崩溃了 这是相关代码ViewControl
  • 为什么Swift标准库中的reverse()函数返回Reverse RandomAccessCollection?

    现在我已经学习了 Swift 达到了合理的水平 我正在尝试掌握标准库 但实际上它对我来说主要是 所以一个具体的问题 我有一个字符串数组 我可以对其调用reverse let arr Mykonos Rhodes Naxos reverse
  • 如何向 hline 添加图例?

    我想在 hline 图中添加一个图例 我的子集的头看起来像这样 Site Date Al 1 Bo6 2014 10 07 152 1 2 Bo1 2014 10 07 157 3 3 Bo3 2014 10 07 207 1 4 Bo4
  • 如何在 python pyqtgraph PlotWidget 中设置刻度标签

    我正在尝试绘制每天几个小时的时间序列 每天之间没有空白时间 如果我使用 pg GraphicsWindow 则效果很好 刻度标签为 9 00 10 00 17 00 如果我使用 pg PlotWidget 或 pg PlotWindow A
  • Python 最佳实践 - 在哪里存储 API 密钥/令牌

    我正在构建一个使用 API 令牌和密钥来访问服务的系统 但存储它们的最佳位置在哪里 我想将代码推送到 GitHub 而不推送令牌 目前 我已将它们放在一个名为的空白文件中Constants py并且 在主 python 文件中 我导入Con
  • 将剪辑路径位置移动到鼠标光标

    我有一个 SVG 形状 用作clip path在图像顶部 SVG 形状应遵循鼠标的位置 如果我使用的话我可以让它工作clip path circle 但如果使用则不然clip path url idOfMask 就像我在使用 SVG 作为剪
  • 如何使用 PHP 将 Word 文档转换为 XML?

    我想将 Word 文档 doc 和 docx 转换为 XML 我如何使用 PHP 来做到这一点 完成此操作后 我必须在该 XML 文件中添加一些数据 有人可以帮我吗 Word 文档 docx 是一个xml文件 只需解压即可
  • 无法从字符串中删除“空字符”

    我问过类似的question https stackoverflow com questions 17580662 how to read a text file that contains null character in delphi
  • 模板中的模板输入和模板引用变量

    我们使用 let 关键字创建模板输入变量 同时使用 var 创建模板引用变量 其中 var 是变量的名称 我们可以在模板中的任何位置引用模板引用变量 模板输入变量的范围怎么样 它与模板引用变量的范围有何不同 有人可以通过例子帮助我理解吗 d
  • 反应本机状态不更新

    我感觉我快要疯了 我在搜索栏中输入 x 但是this setState filter text 没有更新状态 console log this state filter 给我一个值 它的初始值在构造函数中设置 我可以看到文本变量的值为 x
  • 如何在 Python 绘图程序中使用多点触控?

    我正在Python中构建一个简单的绘画程序作为一个项目 使用Pygame 它的工作原理是 当按下鼠标并在表面上拖动它时 它基本上会绘制一系列圆圈 它还有其他一些小事情发生 但事情我想问的是 有没有一种方法可以将您知道的 mouse get
  • Python:获取正则表达式匹配的文本

    我在 Python 中有一个正则表达式匹配对象 我想获取它匹配的文本 说如果模式是 1 3 搜索字符串是 abc123xyz 我想得到 123 我怎样才能做到这一点 我知道我可以使用match string match start matc
  • 仅当设置另一个属性时才需要某个属性

    是否可以做一个属性required如果设置了另一个属性 例如 在下面的代码中 viewId必须制作属性required iff action属性已设置 XML
  • 在 OpenMP 中计算矩阵的条目

    我对 openMP 很陌生 但我正在尝试编写一个简单的程序来并行生成矩阵的条目 即对于 N M 矩阵 A 令 A i j i j 下面包含一个最小的示例 include
  • 任务 - 属性分配

    最初 我有以下内容 foreach Product product in products product ImageUri imageClient GetImageUri product GetImagePath 我想做的是并行处理所有产
  • 诗歌如何知道我的包位于 src 文件夹中?

    我有一个简单的问题 我曾经用我的包在根目录下创建一个诗歌项目 project toml mypackage init py mypackage py test mypackage py 我最近将测试移到了另一个目录中 因此该文件夹现在看起来
  • 赋值使指针无需强制转换

    我正在编辑一个快速排序代码 以便低 高和中的值指向数组元素而不是整数 这是我的代码 include
  • 通过http上传时Android图像损坏

    当我将图像从 Android 设备 v 2 2 上传到服务器 带有 php 的 apache 时 基本上 有与这里相同的问题 Android开发图片上传损坏 https stackoverflow com questions 3154224
  • 创建包含多个 HTTP 请求的 mime/multipart 请求

    我正在关注this http blogs msdn com b webdev archive 2013 11 01 introducing batch support in web api and web api odata aspx使用