Create mime/multipart request containing multiple HTTP requests

风流意气都作罢 提交于 2021-01-27 07:52:20

问题


I am following this tutorial for batching http requests with ASP.NET 4.5. I have the sample working, and now I need to write a client application in Python.

This code creates, and sends a batch request to the 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);

This is my attempt in Python but it doesn't work:

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)

The request should look like this:

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--

回答1:


I've managed to translate the first part of the C# sample into Python using the following code:

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()

All that remains is to figure out how to parse the response(s) from the server.



来源:https://stackoverflow.com/questions/23289602/create-mime-multipart-request-containing-multiple-http-requests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!