aleph

eelke 2021-02-24T08:12:04.002200Z

Hello, I have a question. I am trying to set up a server that can receive and process multipart messages. My attempt is with aleph with yada resources. But I have difficulties in processing the manifold.stream in the response. Do you have some tips and tricks?

eelke 2021-02-24T08:15:44.002600Z

This is the code I have:

(yada/listener
    ["/some-route"
     (yada/resource {:methods
                     {:post {:consumes "multipart/form-data"
                             :produces "application/json"
                             :response (fn [ctx]
                                         (let [boundary (last (clojure.string/split (get-in ctx [:request :headers "content-type"]) #"="))]
                                           (try   (->> (get-in ctx [:request :body])
                                                       (yada.multipart/parse-multipart boundary 10000 1000)
                                                       (manifold.stream/transform (xf-bytes->content))
                                                       manifold.stream/stream->seq)
                                                  (catch Exception e
                                                    (println (.getMessage e)))))
                                         (clojure.data.json/write-str {:success true}))}}})]
    {:port        1234
     :raw-stream? true
     :executor    (flow/utilization-executor 0.9 64)})

mccraigmccraig 2021-02-24T08:25:08.003600Z

what do you want to do with the stream @eelke? note that stream->seq should probably come with a warning - it's a blocking function

eelke 2021-02-24T08:28:33.005300Z

Hey @mccraigmccraig, thanks for the response. I would like to process what comes through the stream. I can be that the client sends large multipart requests, containing tens of images or videos, and the server needs to handle this

eelke 2021-02-24T08:30:12.006600Z

@(d/chain (get-in ctx [:request :body])
           #(manifold.stream/map bs/to-byte-array %)
           #(manifold.stream/reduce conj [] %)
           bs/to-string)
                                                                      

eelke 2021-02-24T08:31:02.007600Z

This does result in a string but it does not always contain everything that was send, I think

mccraigmccraig 2021-02-24T08:33:25.008800Z

ha, i'm recalling a very bad evening spent debugging...

mccraigmccraig 2021-02-24T08:35:15.010100Z

question - do you have {:raw-stream? true} specified in your aleph.http/start-server opts ?

mccraigmccraig 2021-02-24T08:37:37.010400Z

as per: https://github.com/juxt/yada#troubleshooting-faq

mccraigmccraig 2021-02-24T08:38:12.011Z

if you don't, flaky multipart parsing ensues

eelke 2021-02-24T08:39:05.011500Z

ahah, I can imagine. I have it as an option indeed

eelke 2021-02-24T08:39:20.012Z

you can see it in the map I sent with the listener

mccraigmccraig 2021-02-24T08:40:26.012700Z

doh, yeah

eelke 2021-02-24T08:41:00.013100Z

I feel like I am close

mccraigmccraig 2021-02-24T08:51:56.018200Z

i've not been using the stream-based multipart interface - what does yada.multipart/parse-multipart create a stream of ?

eelke 2021-02-24T09:00:24.019300Z

Is there something else you use for multipart?

mccraigmccraig 2021-02-24T09:08:21.020500Z

we've been using the PartConsumer interface ... but iirc that's because that came first and we've been using it since the beginning - i would have preferred a stream-based interface

mccraigmccraig 2021-02-24T09:11:38.021400Z

i'd have a look around for an example of what the canonical yada resource should do now... PartConsumer wasn't the easiest to get working

eelke 2021-02-24T09:24:40.021700Z

ah ok, I'll keep trying