hi
it seems like muuntaja doesn’t like this:
(GET "/echo" req
:summary "foo"
:return {:schema s/Any}
(resp/ok req))
I get:
<h2>HTTP ERROR: 500</h2>
<p>Problem accessing /api/echo. Reason:
<pre> Malformed application/json in :muuntaja/encode</pre></p>
<hr /><i><small>Powered by Jetty://</small></i>
why is that?
req
contains probably stuff that can’t be serialized into JSON in a sensible way. Try returning (pr-str req)
instead.
thanks!
progress, I now get this 500:
< HTTP/1.1 500 Server Error
< Date: Tue, 14 Aug 2018 14:41:30 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 2068
< Server: Jetty(9.2.24.v20180105)
<
* Connection #0 to host localhost left intact
{"schema":"{:schema Any}","errors":"(not (map? a-java.lang.String))","type":"compojure.api.exception/response-validation","coercion":"schema","value":"{:compojure.api.request/muuntaja <<Muuntaja>>, :compojure.api.request/coercion :schema, :compojure.api.request/swagger [{:consumes #{\"application/json\" \"application/transit+msgpack\" \"application/transit+json\" \"application/edn\"}, :produces #{\"application/json\" \"application/transit+msgpack\" \"application/transit+json\" \"application/edn\"}}], :ssl-client-cert nil, :protocol \"HTTP/1.1\", :compojure.api.request/paths {:paths #linked/map [[\"/api/foo\" {:get {:tags #{\"api\"}, :summary \"returns foo\"}}] [\"/api/echo\" {:get {:tags #{\"api\"}, :summary \"echoes the request\", :responses {200 {:schema {:schema Any}, :description \"\"}}}}] [\"/api/hello\" {:get {:tags #{\"api\"}, :parameters {:query {:name java.lang.String}}, :responses {200 {:schema {:message java.lang.String}}, 404 {}, 500 {:schema Any}}, :summary \"greets you\"}}]]}, :remote-addr \"0:0:0:0:0:0:0:1\", :ring.swagger.middleware/data {:info {:title \"Geniki Taxydromiki API\", :description \"\"}, :tags [{:name \"api\", :description \"some apis\"}]}, :params {}, :compojure.api.request/lookup {:compojure.api.swagger/swagger {\"/swagger.json\" {:method :get}}}, :route-handler #function[compojure.core/wrap-response/fn--16907], :route-params {}, :headers {\"user-agent\" \"curl/7.54.0\", \"accept\" \"*/*\", \"host\" \"localhost:8080\"}, :server-port 8080, :muuntaja/request nil, :content-length nil, :form-params {}, :compojure/route [:get \"/echo\"], :query-params {}, :content-type nil, :path-info \"/echo\", :character-encoding nil, :context \"/api\", :uri \"/api/echo\", :server-name \"localhost\", :query-string nil, :muuntaja/response #FormatAndCharset{:format \"application/json\", :charset \"utf-8\"}, :body #object[org.eclipse.jetty.server.HttpInputOverHTTP 0x6c72f437 \"HttpInputOverHTTP@6c72f437\"], :scheme :http, :request-method :get, :route-middleware #function[clojure.core/comp/fn--5529]}","in":["response","body"]}%
I’m not sure how compojure.api decides what content-type to send…
And.. I think this definition
:return {:schema s/Any}
means that it’s expecting a map with key :schema
and any value from the handler. I think you probably want to have just
:return s/Any
correct! I do get a string now
many thanks
No problem!
but still. say I wanted this particular endpoint to return html, how would I do it?
Hmmm I don’t remember from top of my head but you could try returning something like this from the handler
{:status 200
:body "<html><body><p>blabalbal</p></body></html>"
:headers {"Content-Type" "text/html"}}
(GET "/echo" req
:summary "echoes the request"
:return s/Any
(-> (str "<pre>" (with-out-str (pp/pprint req)) "<pre>")
resp/ok
(resp/content-type "text/html")))
this (which I suspect is equivalent to your solution) turns the body into a string first
so it doesn’t render properly
confirmed, the result looks the same as the map that you suggested
I think there is something downstream which quotes my string
(probably muuntaja?)
Hmmm maybe it works if you give it a stream instead of string?
I tested with reitit
library which uses Muuntaja as well and returning a html string from handler with content-type text/html
works as expected
You could try removing :return s/Any
completely and see if that has any effect
How are you testing this btw?
So I tried this (don’t really know what I’m doing but it didn’t work):
(api
{...
:formats {"text/html" {:decode identity
:encode identity}}}
...)
for testing I’m just hitting <http://localhost:8080/api/echo>
And you’re seeing extra quotes around html in http response?
yes
so it looks like it was serialized as a JSON string
it’s not a huge deal, but I’m evaluating compojure-api and I’d like to understand what it does
I can warmly recommend reitit
https://github.com/metosin/reitit
It’s data driven compared to macros in c-api. Makes it easier to understand and use
for a second it looked like bidi and I panicked 😄
However, I’ve had success with c-api in the past as well. 🙂 They’re both good libs but now my vote goes to reitit
I like the more data-driven approach…
and you do get swagger for free, right?
Yes
my only qualm is -SNAPSHOT
https://github.com/metosin/reitit/tree/master/examples/ring-swagger
thanks, I’ll definitely check it out
do you happen to have any inside info on when we could expect a non-snapshot release?
@ikitommi is the author
@ikitommi ☝️ any info on when we could expect a non-snapshot release of reitit?
@stathissideris for c-api, if you define a :return
for an endpoint, it is an "api-response" and is always returned in the negotiated format, e.g. json. This enables returning primitives like Strings & Numbers. For html, just omit the :return
.
oh great, thanks!
I think better would be to have https://github.com/metosin/muuntaja/issues/76
yeah, I guess that would be good too, I think when the user of the API sets their own header it’s like they’re assuming responsibility for formatting the content too, right?
yes, think so too.
the last stable release in reitit
is 0.1.3, but the docs are eagerly promoting the next SNAPSHOT. Will try to push out in the next few days. Actually, the data-driven version of Muuntaja is the last thing to do.
you know, I’ve been on a tour of liberator (a while ago), pedestal, yada, compojure etc, and I think reitit looks like the best fit for my brain. That’s why I’m so eager to use it (great work!)
Thanks! It’s for people who like to be in control of things. No magic, no macros, no default middleware / interceptors. Syntax is “hiccup for routing”. Has been fun trying to make it as fast as possible.
yes exactly, the “magic” is my main problem with the rest of the solutions out there… so about the maturity level of reitit, have you used it production yet? would you recommend it for such use? (I will not consider your reply legally binding 😄 )