I am trying to extract better error message from J...
# http4k
v
I am trying to extract better error message from Jackson deserialization of request Body - within
Filter
implemented in the example I am only getting
400 BAD REQUEST
whereas Jackson provides a nice error description. Is it possible to get this very description to log within the logging filter? https://gist.github.com/knyttl/bd0ffe5474e14a9e64f71d78249bac5b
d
Yep. Catch the LensFailure that is thrown and you will be able to get the message from there. You'll have to wrap the handler that is returned in the bindContract call instead of wrapping the contract itself. (Because the contract handler also contains a catch filter)
v
I tried googling and find this:
Copy code
val jsonResultLens = Body.json().toLens().asResult()
    val jsonResult: Result<JsonNode, LensFailure> = jsonResultLens(Request(GET, "/foo"))
    println(jsonResult)
is this what you meant? using
jsonResultLens
within the filter? however the method
.asResult()
seems to be missing - hasn't it been removed?
d
Result wasn't removed. but you do need to include result4k manually. However, this will do what you want: https://gist.github.com/daviddenton/49d397479f2bf7e3ba48182d0a783483
also - one more thing - when you're posting Gists, please include an entire runnable example including imports so that it's easy for everyone to run exactly the same thing instead of having to rewrite it. 🙂
v
okay, will do next time
hm in fact - i don't get any exception
no lensfailure
just response=400, message "400 BAD REQUEST"
Copy code
val loggingFilter = Filter { next: HttpHandler ->
            { request: Request ->
                val response = next(request)
                <http://log.info|log.info>(response.status.description)
                // 400 BAD_REQUEST, no error details
                response
            }
        }
you can see here, that this is just response.status, no LensFailure exception
I think your example throws LensFailure on response.body, i have issues with request.body
d
Set the pre extraction to no body. It's not getting to the handler (my example didn't declare the input lens)
And yes - another reason to always use full examples. 😉
v
updated: https://gist.github.com/knyttl/2f380a060e3cf4f86baeecab5ce24096 however still no exception, only 400 BAD REQUEST
(I also tried
PreFlightExtraction.Companion.None
, but still no exception within the logging filter)
d
that's because you're still not trapping the error. look again at the Gist I sent. 🙂
v
trapping the erorr
you mean the exception catching here:
Copy code
try {
                next(it)
            } catch( e: LensFailure){
                Response(BAD_REQUEST).body(e.cause?.localizedMessage ?: "")
            }
?
there is no exception thrown
d
The output of: https://gist.github.com/daviddenton/49d397479f2bf7e3ba48182d0a783483 on my machine is:
Copy code
HTTP/1.1 400 Bad Request


Unexpected end-of-input: was expecting closing quote for a string value
 at [Source: (String)"{"name":"}"; line: 1, column: 11] (through reference chain: Blob["name"])
v
Copy code
fun CatchLensFailure(failResponseFn: (LensFailure) -> Response = {
        Response(BAD_REQUEST.description(it.failures.joinToString("; ")))
    }) = Filter { next ->
        {
            try {
                next(it)
            } catch (lensFailure: LensFailure) {
                when {
                    lensFailure.target is Response -> throw lensFailure
                    lensFailure.target is RequestContext -> throw lensFailure
                    lensFailure.overall() == Failure.Type.Unsupported -> Response(UNSUPPORTED_MEDIA_TYPE)
                    else -> failResponseFn(lensFailure)
                }
            }
        }
    }
It seems it ends here in the
else
branch - it catches the exception and retruns response
in your gist you do it differently - i need the filter to be out of the handler (i want to have it general for all handlers), note I have
loggingFilter.then(handler)(request)
d
yes. that's not supported
because you can't override the CatchLensFailure inside the contract handler
v
sso basically i cannot have general filter which would look after all lensexceptions
d
basically
v
and there is no way to overcome this?
d
not at the moment
v
does it make sense to you if I create an issue for it?
d
Actually - I'm being an idiot. There is a way to customise it - you need to provide your own ErrorResponsrRenderer - https://github.com/http4k/http4k/blob/55ae8008df9500203fc1bfe05f244c3da58992c1/http4k-contract/src/main/kotlin/org/http4k/contract/openapi/v3/OpenApi3.kt#L54
Completely forgot about that. 🤣
(But it won’t work in any example where you don’t set the renderer up)
v
hmm, but doesn't this seem to work only for OpenApi? does it mean, that once I setup OpenApi, this will start to work?
🙂 thanks, will try