Hello everybody. We are working on a "flexible HTTP Processor", that allows the user to setup a reverse proxy for custom access control, openid authentication, logging and troubleshooting, payload signing and things like that. We used manifold/aleph as the basis for the server. See https://codeberg.org/jomco/passage I'm working on a request validator interceptor now. In order to fully validate requests we need to read the request body, validate its content and if successful, forward the request (proxy to a backend service). From my experiments I see that incoming requests in aleph.http have an java.io.InputStream as request body. How should we handle an InputStream in an aleph/manifold context? Run any processing in a separate thread? Is it possible to receive the request body in some other non-blocking form? Any hints or links to relevant documentation would be appreciated.
Hi! Your best option currently would be the raw-stream? option (see start-server)
(couldn't use Markdown link syntax anymore for some reason)
This means you'll have to make sure to https://cljdoc.org/d/aleph/aleph/0.9.11/api/aleph.netty#release every bytebuf manually
If you need to read the whole body anyway to validate it, I recommend putting an HttpObjectAggregator to your pipeline. That will make Netty do the reading for you and Aleph will invoke your handler with a byte array as :body.
The latter would be without :raw-stream? true
you can also achieve this as a side-effect of passing a max-request-body-size to start-server (see https://github.com/clj-commons/aleph/issues/692)
both are somewhat reliant on implementation details which are unlikely to change tho
HTH!
Ah thanks @dergutemoritz I will take a look at your suggestions!
If I understand your comments correctly, these options all apply to the whole netty server, correct? That means if we set a max-request-body-size that would apply to all the incoming requests, not just the once we would validate.
correct
ok, thanks again!
hm hold on, just tried to verify this and it appears you would still receive an InputStream when using an HttpObjectAggregator
lemme check
ah right, my bad
it is still wrapped in a ByteArrayInputStream to comply with the ring spec, of course
so reading from it would be guaranteed to not block but I guess it's still not ideal
You could combine it with :raw-stream? in which case you'd get a manifold stream with a single buffer in it - that's a bit easier to manage than a stream of multiple buffers and less indirection than going through the input stream I suppose
(d/chain' (s/take! (:body req)) netty/release-buf->array) should do the trick then (where netty is aleph.netty)
I guess it would be nice to have an :as coercion option like the client does