reitit

Luca Bandelli 2025-03-05T13:39:32.491849Z

Hello everyone! I'm porting an old java servlet application (yay 😅) to clojure with reitit. For all of the JSON based endpoints it's been truly only pleasure and joy! (Thanks for awesome project!!) On the other hand i have to implement a single XML based route that takes in an XML document from the request body, enriches it and returns the enriched document as response body. I saw something here about returning xml https://github.com/metosin/reitit/blob/master/doc/ring/content_negotiation.md but not much else. Does anyone have some pointers or snippets that may help me? Thanks in advance! (i have tried discussing this with various gpts but i feel they are leading my astray)

opqdonut 2025-03-05T13:52:36.074599Z

you can return xml by having your handler output something like

{:status 200
 :body ""
 :headers {"Content-Type" "application/xml"}}
edit: application/xml of course!

opqdonut 2025-03-05T13:53:06.986749Z

the reitit/muuntaja magic only happens if your :body is a clojure map, muuntaja can then convert that to json, edn, transit, etc. depending on the Accept headers in the request

opqdonut 2025-03-05T13:53:29.819679Z

similarly, muuntaja won't decode an XML request body for you, you'll just get it as a string

Luca Bandelli 2025-03-05T14:29:02.056339Z

@joel.kaasinen and @vale thanks both for your time! @joel.kaasinen i think in your solution the output would be an xml string but with "" around, so this would not interop with xml logic. @vale i think this is exactly the kind of pattern I was looking for thanks so much i'll dig into it ❤️

1
opqdonut 2025-03-05T14:31:45.391219Z

what's "the output"? if you give a string to :body, the contents of that string will be the contents of the HTTP response, without any formatting

valerauko 2025-03-05T14:33:21.017109Z

Lying about the content-type is not a good practice though

opqdonut 2025-03-05T14:33:42.817089Z

I'm sorry I'm not following you

opqdonut 2025-03-05T14:34:21.074539Z

an example:

valerauko 2025-03-05T14:34:31.126009Z

You had application/json for xml content

opqdonut 2025-03-05T14:35:10.704799Z

route definition:

(def routes
  ["/plain"
   ["/foo" {:get {:handler (fn [req]
                             {:status 200
                              :headers {"content-type" "application/xml"}
                              :body "<xml></xml>"})}}]])
curl:
% curl -v 
*   Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /plain/foo HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.83.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Wed, 05 Mar 2025 14:34:08 GMT
< Content-Type: application/xml
< Transfer-Encoding: chunked
< Server: Jetty(11.0.20)
<
* Connection #0 to host localhost left intact
<xml></xml>

opqdonut 2025-03-05T14:35:28.155839Z

oh yeah sorry, that was a very confusing typo from me facepalm 🤦

opqdonut 2025-03-05T14:36:07.173479Z

I meant application/xml, not sure what went into my fingers

👍 1
😇 1
opqdonut 2025-03-05T14:37:10.492059Z

anyway, my point is that if you have a single xml endpoint, you can just bypass the muuntaja & reitit stuff like this. if you have a lot of xml stuff then you probably want some middleware that converts between xml and clojure data, like in valerauko's example.

👍 1
🚀 1
Luca Bandelli 2025-03-05T15:28:37.630649Z

Great thank again to you both 🙂