apiaryio / api-blueprint

API Blueprint
https://apiblueprint.org
MIT License
8.64k stars 2.14k forks source link

A nicer way to express multipart form submission (with images) #100

Open ErikPettersson opened 10 years ago

ErikPettersson commented 10 years ago

Instead of

+ Request (multipart/form-data;boundary=----WebKitFormBoundary8M3sSU13ul5lXSJm)
    + Headers

            Authorization: qwertyqwerty

    + Body

            ------WebKitFormBoundary8M3sSU13ul5lXSJm
            Content-Disposition: form-data; name="json"

            {"name":"test"}
            ------WebKitFormBoundary8M3sSU13ul5lXSJm

            Content-Disposition: form-data; name="image"; filename="filename.jpg"
            Content-Type: image/jpeg

            data
            ------WebKitFormBoundary8M3sSU13ul5lXSJm--

I'd like a shorthand to express the different form fields and their types so I don't have to format this manually.

With Dredd this doesn't work against my Node Express server with multiparty for body parsing since it depends on correct line endings when parsing \r\n vs \n or somesuch, which is very hard to get correct in the Blueprint document (even more so when version control gets involved).

Not sure if the multiparty parser should accept the line endings Dredd sends, or if the bug is within multiparty.

Either way a shorthand would be nice to make it a bit easier to read and understand.

ErikPettersson commented 10 years ago

(Issue #100!)

ErikPettersson commented 10 years ago

Since it's closed in dredd this would fall on Blueprint then. Bug since it doesn't work currently, Feature Request for nicer syntax.

zdne commented 10 years ago

What about this?

+ Request (multipart/form-data;boundary=----WebKitFormBoundary8M3sSU13ul5lXSJm)
    + Headers

            Authorization: qwertyqwerty

    + Part
        + Headers

                Content-Disposition: form-data; name="json"

        + Body 

                {"name":"test"}

    + Part
        + Headers

                Content-Disposition: form-data; name="image"; filename="filename.jpg"

        + Body 

                data
ErikPettersson commented 10 years ago

Way better, but when we're on this path couldn't it be taken even further? Setting the boundary seems like overkill when it's not explicitly used anywhere. I think headers would most often just be the name of the form part, so that could be condensed even further.

It would be nice to have your suggested syntax for when it's actually needed, but it's still a bit on the long side.

+ Request (multipart/form-data)
    + Headers

             Authorization: qwertyqwerty

    + Part (name="json")

            {"name":"test"}

    + Part (name="image"; filename="filename.jpg")

            data
zdne commented 9 years ago
pksunkara commented 9 years ago

We should probably also look at referencing files in API Blueprint for this.

zdne commented 9 years ago

We should probably also look at referencing files in API Blueprint for this.

Not necessarily. This should work even without using referencing / external asset

zdne commented 9 years ago

However once external assets #20 are developed this should be taken into account.


Note @pksunkara please do not forget to interlink issues in a future if you are making reference to another issue

tobyberesford commented 8 years ago

+1 for this. I agree syntax could be a lot easier and clearer. I actually think the image upload is an edge case. In our API we use multipart/form-data for all our POST requests.

pandres95 commented 8 years ago

šŸ‘ Waiting for it to be implemented!

thomasbalsloev commented 7 years ago

Any status on this?

eimantas commented 7 years ago

bump. šŸ‘

vnenkpet commented 7 years ago

:+1:

FFX01 commented 7 years ago

What's the status for support regarding this issue? Is this something I could help implement?

kylef commented 7 years ago

@FFX01 There hasn't been any updates on this, but this is certainly something you can help implement.

The first step would be to define the syntax for describing multi part in API Blueprint. To do this you would start by writing an RFC by putting some thought into the design and provide a specification for how this addition to the language would look. More information about our RFC process can be found at https://github.com/apiaryio/api-blueprint-rfcs.

Once we have an RFC we will review and iterate until we're happy and are able to accept the proposal. Once it's accepted this can be then implemented in the API Blueprint specification and parsers.

I'd suggest that the syntax should sit on-top of MSON and use MSON concepts as much as possible.

Here's some ideas to extend MSON to add Multipart. I'd think multipart should be completely described in MSON attributes.

+ Request (multipart/form-data)
    + Attributes
        + Part
            + name: json
            + body (application/json)
                + Attributes (Person)
        + Part
            + filename: `example.jpeg`
        + Part
            + name: example
            + body: `Hello World!` (text/plain)

Where you would define your Multipart parts, these could actually be re-usable MSON data structures. You could then allow user any headers data in the part itself with an optional example body. The example body could either be "raw" example, or it could be an MSON structure itself.

Example of re-usable multi-part form parts:

## POST /

+ Request (multipart/form)
    + Attributes
        + AuthorizationPart
        + Part
            + name: body

## Data Structure
### AuthorizationPart (Part)
+ name: json
+ body (application/json)
    + Attributes
        + type: Bearer (fixed)
        + token: dc11f13f1174c981a6582e6e62325b17e13711c6

Example of a complete set of reusable parts:

## POST /

+ Request (multipart/form)
    + Attributes (UserMultipart)

## PATCH /user/{username}

+ Request (multipart/form)
    + Attributes (UserMultipart)
        + Part
            + name: `example-inheritance`

## Data Structure
### UserMultipart (Multipart)

+ AuthorizationPart
+ Part
    + name: body

### AuthorizationPart (Part)

+ name: json
+ body (application/json)
    + Attributes
        + type: Bearer (fixed)
        + token: dc11f13f1174c981a6582e6e62325b17e13711c6

One design decision I think we should keep in mind it we want to avoid adding new syntax specifically for a fixed content-type such as multipart form, but instead allow describing multipart in a serialisation agnostic way as much as possible. I don't think it's beneficial in the long term if there are many different syntaxes for each type of serialisation.

zeusent commented 4 years ago

It's been almost 6 years now. Is this a thing now or still not possible to document a multipart/form-data request?

zhanglin-wu commented 3 years ago

Can we support Content-Type: multipart/mixed; boundary=sjp6mhw7bk8 as well because multipart/mixed is just one of the multipart payloads?