# Send multipart request from julia using HTTP.jl

**URL:** https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148
**Category:** New to Julia
**Created:** [April 28, 2021, 7:33am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148 "2021-04-28T07:33:00Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![Michal](https://avatars.discourse-cdn.com/v4/letter/m/34f0e0/32.png) [@Michal](https://discourse.julialang.org/u/Michal)
#### Post date: [April 28, 2021, 7:33am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/1 "2021-04-28T07:33:00Z")

</div>

How can I send multipart request using HTTP.jl where first part is json ans seocnd is csv file?

```julia
HTTP.request("POST"...

```

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [April 28, 2021, 9:27am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/2 "2021-04-28T09:27:19Z")

</div>

```julia
import HTTP

url = "http://localhost:8080";

open("file.json") do json; open("file.csv") do csv
    headers = []
    body = HTTP.Form([
        "json" => json,
        "csv" => csv
    ])
    HTTP.post(url, headers, body)
end end

```

(You can check the request with e.g. `netcat -lp 8080`)

See documentation for [`HTTP.Form`](https://juliaweb.github.io/HTTP.jl/stable/public_interface/#HTTP.Form) (and [`HTTP.Multipart`](https://juliaweb.github.io/HTTP.jl/stable/public_interface/#HTTP.Multipart)), and [Julia HTTP POST request with image attachment - Stack Overflow](https://stackoverflow.com/a/66276751/5087136)

---

<div class="post-metadata">

### Author: ![Michal](https://avatars.discourse-cdn.com/v4/letter/m/34f0e0/32.png) [@Michal](https://discourse.julialang.org/u/Michal)
#### Post date: [April 28, 2021, 10:09am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/3 "2021-04-28T10:09:45Z")

</div>

Thank you. I think it is working, but I need to add filename of csv. Please, do you know how to add filename for it?

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [April 28, 2021, 10:12am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/4 "2021-04-28T10:12:08Z")

</div>

Did you read the documentation I linked? It is explained there, and also in the SO answer.

---

<div class="post-metadata">

### Author: ![Michal](https://avatars.discourse-cdn.com/v4/letter/m/34f0e0/32.png) [@Michal](https://discourse.julialang.org/u/Michal)
#### Post date: [April 28, 2021, 10:26am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/6 "2021-04-28T10:26:05Z")

</div>

I tried mentioned advice:

```julia
url="http://$hostname:$port/myEndPoint"
headers = ["X-User-Id" => "d5as4d654asd65a64s5dad6a"]

body = HTTP.Form(Dict(
            "json" => HTTP.Multipart("data.json", open("data.json"), "text/json"),
            "csv" => HTTP.Multipart("data.csv", open("data.csv"), "text/csv"),
        ))

res = HTTP.post(url, headers, body)
        
inputJson = JSON.parse(String(req.body))

```

but I still getting an error with filename:

```julia
Got exception outside of a @test
  HTTP.ExceptionRequest.StatusError(400, "POST", "/myEndPoint", HTTP.Messages.Response:
  """
  HTTP/1.1 400 Bad Request
  Content-Type: application/json
  Transfer-Encoding: chunked
  
  {"status":"InvalidInputData","description":"Item fileName is not recognized."}""")
  Stacktrace:
    [1] request(::Type{ExceptionLayer{ConnectionPoolLayer{StreamLayer{Union{}}}}}, ::URIs.URI, ::Vararg{Any, N} where N; kw::Base.Iterators.Pairs{Symbol, Union{Nothing, Bool}, Tuple{Symbol, Symbol}, NamedTuple{(:iofunction, :reached_redirect_limit), Tuple{Nothing, Bool}}})
      @ HTTP.ExceptionRequest ~/.julia/packages/HTTP/dCYNB/src/ExceptionRequest.jl:22

```

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [April 28, 2021, 10:39am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/7 "2021-04-28T10:39:02Z")

</div>

Then you need to consult the documentation of the API you are using, maybe the names have to be something specific.

---

<div class="post-metadata">

### Author: ![Michal](https://avatars.discourse-cdn.com/v4/letter/m/34f0e0/32.png) [@Michal](https://discourse.julialang.org/u/Michal)
#### Post date: [April 30, 2021, 8:53am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/8 "2021-04-30T08:53:00Z")

</div>

I have another issue related to multipart. It looks like PUT is not working correctly. I tried same example for POST and PUT. Same example worked for POST and didn’t work for PUT.

When I ran it in swagger or with CURL command, PUT option was working. When I used following code using HTTP.jl it was failing on side of server in function “HTTP.parse\_multipart\_form(req)”. I don’t understand why it is working with swagger, curl, but not working with HTTP.jl.

Working POST:

```julia
url = "http://$hostname:$port/datasets/csv"
headers = ["X-User-Id" => "9997773e-7e42-40d1-896b-5659a6229066",
"Content-Type"=> "multipart/form-data"]

mpdt = Vector{Pair}(undef, 2)
mpdt[1] = "configuration" => open("Upload.json")
mpdt[2] = "csv" => HTTP.Multipart("Upload.csv", open("Update.csv"), "text/csv")

body = HTTP.Form(mpdt)
res = HTTP.request("POST", url, headers, body)

```

Not working PUT:

```julia
url = "http://$hostname:$port/datasets/$(datasetId)/csv"
headers = ["X-User-Id" => "9997773e-7e42-40d1-896b-5659a6229066",
"Content-Type"=> "multipart/form-data"]

mpdt = Vector{Pair}(undef, 2)
mpdt[1] = "configuration" => open("Update.json")
mpdt[2] = "csv" => HTTP.Multipart("Update.csv", open("Update.csv"), "text/csv")

body = HTTP.Form(mpdt)
res = HTTP.request("PUT", url, headers, body)

```

Missing is boundary for HTTP.jl request. Is something wrong in my code or in HTTP.jl?

From swagger:

```julia
"""
PUT /datasets/d891d099-9e90-4b63-95cb-f889670989fc/csv HTTP/1.1
X-User-Id: 1127773e-7e42-40d1-896b-5659a6ce9066
Content-Type: multipart/form-data; boundary=---------------------------84871092641888763363568039506
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:8080/swagger-ui

Origin: http://localhost:8080
Content-Length: 584
Connection: keep-alive

-----------------------------84871092641888763363568039506
Content-Disposition: form-data; name="configuration"

{
    "att1": "va1",
    "att2": "va2l",
    "att3": "val3"
}
-----------------------------84871092641888763363568039506
Content-Disposition: form-data; name="file"; filename="Update.csv"
Content-Type: text/csv

Date;pA;pB;pC
2004-01-01 01:00:00;2;22;222
2004-01-01 03:00:00;4;44;444
2004-01-01 05:00:00;6;66;666
-----------------------------84871092641888763363568039506--
"""

```

From HTTP.jl

```julia
"""
PUT /datasets/d891d099-9e90-4b63-95cb-f889670989fc/csv HTTP/1.1
X-User-Id: 1127773e-7e42-40d1-896b-5659a6ce9066
Content-Type: multipart/form-data;
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:8080/swagger-ui

Origin: http://localhost:8080
Content-Length: 584
Connection: keep-alive

-----------------------------84871092641888763363568039506
Content-Disposition: form-data;

{
    "att1": "va1",
    "att2": "va2l",
    "att3": "val3"
}
-----------------------------84871092641888763363568039506
Content-Disposition: form-data; name="file"; filename="Update.csv"
Content-Type: text/csv

Date;pA;pB;pC
2004-01-01 01:00:00;2;22;222
2004-01-01 02:00:00;4;44;444
2004-01-01 03:00:00;6;66;666
-----------------------------84871092641888763363568039506--
"""

```

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [April 30, 2021, 9:04am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/9 "2021-04-30T09:04:38Z")

</div>

HTTP.jl only adds the `Content-Type` automatically for `POST`: [https://github.com/JuliaWeb/HTTP.jl/blob/255a75907a06b1340e7deac659383f15f3aa55f0/src/MessageRequest.jl#L58-L61](https://github.com/JuliaWeb/HTTP.jl/blob/255a75907a06b1340e7deac659383f15f3aa55f0/src/MessageRequest.jl#L58-L61).

I [added](https://github.com/JuliaWeb/HTTP.jl/pull/473) that code [but didn’t know if it made sense for any other request types](https://github.com/JuliaWeb/HTTP.jl/issues/489#issuecomment-567148992). You can probably make a PR and relax that to `POST` or `PUT` at least.

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [September 27, 2021, 8:08am UTC](https://discourse.julialang.org/t/send-multipart-request-from-julia-using-http-jl/60148/10 "2021-09-27T08:08:26Z")

</div>

I [added this](https://github.com/JuliaWeb/HTTP.jl/pull/770), will be available in [HTTP.jl 0.9.15](https://github.com/JuliaWeb/HTTP.jl/blob/master/CHANGELOG.md#0915---2021-09-27).
