responsemultipartform-datadenooak

Use FormData in an HTTP Response in Deno/Oak


I know that I can create a FormData in the client and send it to the server (in this case I'm using Deno/Oak), and read it from there.

But is this possible vice versa?

If I have a route in Oak, and I want it to send a multipart response (with one or more blobs, and with one or more strings), how can I do it?


Solution

  • Oak's automatic response body handling supports FormData so you can set context.response.body to an instance of FormData and Oak will take care of the rest. e.g.:

    import { Application } from "https://deno.land/x/oak@v9.0.0/mod.ts";
    
    const app = new Application();
    
    app.use((ctx) => {
      const data = new FormData();
      data.append("string1", "Hi");
      data.append("string2", "Bye");
      data.append("blob1", new Blob(['<a id="a">Hi</a>'], { type: "text/xml" }));
      data.append("blob2", new Blob(['<b id="b">Bye</b>'], { type: "text/xml" }));
      ctx.response.body = data;
    });
    
    await app.listen({ port: 8000 });
    
    % curl localhost:8000
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="string1"
    
    Hi
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="string2"
    
    Bye
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="blob1"; filename="blob"
    Content-Type: text/xml
    
    <a id="a">Hi</a>
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="blob2"; filename="blob"
    Content-Type: text/xml
    
    <b id="b">Bye</b>
    ------7115155097707325061106360125--
    

    The same can be done directly in Deno without any additional framework:

    const server = Deno.listen({ port: 8000 });
    
    for await (const conn of server) serveHttp(conn);
    
    async function serveHttp(conn: Deno.Conn) {
      const httpConn = Deno.serveHttp(conn);
      for await (const requestEvent of httpConn) {
        const data = new FormData();
        data.append("string1", "Hi");
        data.append("string2", "Bye");
        data.append("blob1", new Blob(['<a id="a">Hi</a>'], { type: "text/xml" }));
        data.append("blob2", new Blob(['<b id="b">Bye</b>'], { type: "text/xml" }));
        requestEvent.respondWith(new Response(data));
      }
    }