0

I'm building a Web App based on Dart (with polymer framework but that's not relevant for the question). My app is communicating with a HTTP RESTful server.

Problem is that i'm trying to send an HTTP Post request in multipart, but I couldn't find a way to set the 'Content-Type' for each part of the body (and not for the main HTTP header, which is rightly set by dart to 'multipart/form-data')

Here is a simple repro of my http request :

import 'dart:html';
import 'dart:convert';

main(){

  print("je suis dans dart");

  Map jsontosend = {
      'business-context-id': "contexte1",
      'metadatas': [
          {"metadata-id" : "nom", "value" : "doe"},
          {"metadata-id" : "prenom", "value" : "john"}],
  };

  FormData form = new FormData();

  form.append("context", JSON.encode(jsontosend));

  HttpRequest.request("www.google.com", method: "POST", sendData: form);

}

Here is my request payload :

Remote Address:127.0.0.1:63342
Request URL:http://localhost:63342/http_test/web/www.google.com
Request Method:POST
Status Code:405 Method Not Allowed
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:263
Content-Type:multipart/form-data; boundary=----WebKitFormBoundarym9PvtGzZDKOKiaH1
Host:localhost:63342
Origin:http://localhost:63342
Referer:http://localhost:63342/http_test/web/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.0 (Dart) Safari/537.36
Request Payload
------WebKitFormBoundarym9PvtGzZDKOKiaH1
Content-Disposition: form-data; name="context"

{"business-context-id":"contexte1","metadatas":[{"metadata-id":"nom","value":"doe"},{"metadata-id":"prenom","value":"john"}]}
------WebKitFormBoundarym9PvtGzZDKOKiaH1--

The server i'm trying to call can't parse the 'context' part as there is no content-type provided.

I also tried to 'convert' my json as a blob object :

import 'dart:html';
import 'dart:convert';

main(){

  print("je suis dans dart");

  Map jsontosend = {
      'business-context-id': "contexte1",
      'metadatas': [
          {"metadata-id" : "nom", "value" : "doe"},
          {"metadata-id" : "prenom", "value" : "john"}],
  };

  FormData form = new FormData();

  Blob blob = new Blob([JSON.encode(jsontosend)], 'application/json', 'native');

  form.appendBlob("context", blob);

  HttpRequest.request("www.google.com", method: "POST", sendData: form);

}

And the associated payload :

Remote Address:127.0.0.1:63342
Request URL:http://localhost:63342/http_test/web/www.google.com
Request Method:POST
Status Code:405 Method Not Allowed
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:312
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryjHxHOCKDpsp22rzQ
Host:localhost:63342
Origin:http://localhost:63342
Referer:http://localhost:63342/http_test/web/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.0 (Dart) Safari/537.36
Request Payload
------WebKitFormBoundaryjHxHOCKDpsp22rzQ
Content-Disposition: form-data; name="context"; filename="blob"
Content-Type: application/json


------WebKitFormBoundaryjHxHOCKDpsp22rzQ--

This time, the Content-Type of the context part is set, but my json is 'wrapped' as a blob (converted to Base64 by dart framework?) and can't be parsed by the server.

As soon as I use the Blob type, the filename attribute is set, and the server also rejects the request.

Any idea ?

Thanks in advance !

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I haven't used multipart requests before but mabe this is of some help http://stackoverflow.com/a/22604319/217408 – Günter Zöchbauer Jan 28 '15 at 13:46
  • I use the same kind of code on the client side to post datas to a java backend and it works well. It seems to be a problem on the server side. – Alexandre Ardhuin Jan 28 '15 at 14:00
  • Thanks for your answers. @GünterZöchbauer the MultipartRequest object has two methods to add 'part' to your request : fields to add 'text' part (json / xml ..) and file to add file. The file method allows you to define Content-Type (as shown in example), but unfortunately you can't set it with the fields method. – Julien Bertrand Jan 28 '15 at 23:25
  • @AlexandreArdhuin it's not a problem on the server side. As it accepts both json and xml, it has to be able to perform content negotiation. They're asking for all front-end app to specify their content-type (there is no default value) – Julien Bertrand Jan 29 '15 at 08:46
  • But in your last code snippet the Content-Type is well provided for the "context" part. So I don't understand your comment. – Alexandre Ardhuin Jan 29 '15 at 10:24

1 Answers1

1

I could find a solution. The trick was to specifiy a filename with a .json extension when appending the blob to the form.

import 'dart:html';
import 'dart:convert';

main(){

  Map jsontosend = {
      'business-context-id': "contexte1",
      'metadatas': [
          {"metadata-id" : "nom", "value" : "doe"},
          {"metadata-id" : "prenom", "value" : "john"}],
  };

  FormData form = new FormData();

  Blob blob = new Blob([JSON.encode(jsontosend)], 'application/json', 'native');

  form.appendBlob("context", blob, "whatever.json");

  HttpRequest.request("www.google.com", method: "POST", sendData: form);

}

However, I still don't know how to specifiy the Content-Type when using a text part.

Thanks all for your help !

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567