ring

Saket 2023-09-26T19:55:56.456079Z

When I return a (bad-request! {:message "Something is wrong with the request"}) I get 500 Internal error on the client. How to get 400 Bad request instead ?

DrLjรณtsson 2023-09-27T20:57:21.591989Z

I believe bad-request! throws so you need to catch that exception . Try using bad-request instead (without !)

Saket 2023-09-28T05:12:26.385389Z

Hey, sorry for the late response. @seancorfield, bad-request! is the standard ring.util.response/bad-request! It is supposed to throw an error, which it does. But that exception gets translated into 500 Internal for the client. It should ideally be converted to 400 Bad request error, like it does in other language's frameworks.

Saket 2023-09-28T05:13:34.221299Z

@brjann, bad-request just returns 200 OK with error info in the response body.

seancorfield 2023-09-28T05:13:59.472499Z

It shouldn't be 400 Bad Request. That's not the semantically correct HTTP status code.

seancorfield 2023-09-28T05:14:37.532519Z

See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses for example. 5xx is the correct status for a server error.

seancorfield 2023-09-28T05:15:15.409949Z

4xx are client errors -- indicating that the client needs to do something different.

seancorfield 2023-09-28T05:15:46.029689Z

I don't know of any language framework that returns a 4xx error for an unhandled error on the server -- that's just semantically wrong.

Saket 2023-09-28T05:18:23.863999Z

According to MDN: The server has encountered a situation it does not know how to handle. But, I would say that the server handled the situation and returned the bad-request so that the client gets 400. Am I missing a middleware here? I used django and spring boot in the past and noticed the behaviour that I was expecting. Let me double check if I missed a middleware somewhere that translates responses and throws corresponding http error

seancorfield 2023-09-28T05:18:29.573039Z

ring.util.response/bad-request is for returning a 400:

> clj -Sdeps '{:deps {ring/ring {:mvn/version "RELEASE"}}}'
Clojure 1.12.0-alpha4
user=> (require '[ring.util.response :as resp])
nil
user=> (resp/bad-request {:error "failed!"})
{:status 400, :headers {}, :body {:error "failed!"}}
user=>

seancorfield 2023-09-28T05:19:46.828509Z

If you are using bad-request and don't get a 400 status like I showed, then maybe you have middleware that is messing with the response?

seancorfield 2023-09-28T05:21:09.443849Z

@brjann There's no bad-request! in https://ring-clojure.github.io/ring/ring.util.response.html What is that bad-request! call @saket.is.sam?

Saket 2023-09-28T05:22:34.097729Z

I do get a response just like the one you shared. But the client gets the http response 200 and this map in the response body. Now, if I have to handle this on client I have to write extra code that checks for this response for any possible error (as the server said: well, it worked and here is an error in the response body) If it threw the exception I could wrap the client request in a try/catch block and be done with it.

seancorfield 2023-09-28T05:23:00.968649Z

bad-request returns a 400 status, not a 200 status.

seancorfield 2023-09-28T05:23:11.701209Z

You must have something else messing with the response.

seancorfield 2023-09-28T05:24:06.238909Z

(I know this works -- we return 4xx status a lot in our app at work)

Saket 2023-09-28T05:25:52.530359Z

I believe we are talking about two different places when we talk about status. You're talking about the return value of (bad-request ...) I am talking about when it translates finally for a client that sent the http request. It translates to HTTP 200 and the response body has:

{:status 400
 ...}

seancorfield 2023-09-28T05:26:33.786069Z

Then you have SOMETHING ELSE MESSING WITH THE RESPONSE. I'm telling you that does not happen by default.

Saket 2023-09-28T05:26:33.954189Z

Oh let me check again, maybe I missed something here. I'll update here if I find anything.

seancorfield 2023-09-28T05:26:55.192769Z

If you shared some code, that might help.

seancorfield 2023-09-28T05:27:29.109669Z

But, right now, I'm pretty sure you're just doing something "wrong" with the Ring response somewhere in your stack.

seancorfield 2023-09-28T05:28:17.694079Z

Perhaps you're doing the equivalent of this?

user=> (resp/response (resp/bad-request {:error "failed!"}))
{:status 200, :headers {}, :body {:status 400, :headers {}, :body {:error "failed!"}}}

โž• 1
Saket 2023-09-28T05:28:40.864319Z

Got it. I'll share a snippet when I get back to the project.

seancorfield 2023-09-28T05:29:36.073859Z

Somewhere in your code, you probably need logic like this:

user=> (let [r (resp/bad-request {:error "failed!"})]
         (if (resp/response? r)
           r
           (resp/response r)))
{:status 400, :headers {}, :body {:error "failed!"}}

seancorfield 2023-09-28T05:30:14.118139Z

i.e., in your middleware, you might need to see if you already have a Ring response before just wrapping the result in a response.

seancorfield 2023-09-28T05:31:42.570079Z

And a regular (non-error) flow would be:

user=> (let [r {:success true :message "Yay!"}]
         (if (resp/response? r)
           r
           (resp/response r)))
{:status 200, :headers {}, :body {:success true, :message "Yay!"}}

seancorfield 2023-09-28T05:33:12.665589Z

(your avatar might trigger coulrophobia ๐Ÿ™‚ ๐Ÿ™‚ ๐Ÿ™‚ )

Saket 2023-09-28T06:01:38.340129Z

Sean, you are right. There's no middleware issue, just my dumb ass wrapped the response in ok at the top level. Sorry for wasting your time. These ok, bad-request! are a part of metosin/ring-http-response lib.

Saket 2023-09-28T06:03:46.655509Z

Updated the profile picture.

seancorfield 2023-09-28T06:16:58.818439Z

> wrapped the response in ok at the top level Ah, much like my (resp/response (resp/bad-request ..)) above? > metosin/ring-http-response lib Good to know. Probably important to mention that when asking Ring questions in future. > Updated the profile picture. I was (mostly) joking. Nice beach! Where was that taken?

Saket 2023-09-28T06:42:01.288409Z

> Ah, much like my (resp/response (resp/bad-request ..)) above? Yup. > Good to know. Probably important to mention that when asking Ring questions in future. I'll make sure about that from the next time. I was on the phone before and it's so annoying to type out on phone and didn't completely remember the lib name. > I was (mostly) joking. It was a gmail picture from years ago and needed to be updated anyway. Thanks for reminding. > Nice beach! Where was that taken? It's called the Rock Beach in Puducherry, India. Picture is from a recent trip with my friends. ๐Ÿ™‚ Thanks again for your time.

Saket 2023-09-28T06:43:44.425399Z

BTW, forgot to mention that I loved your REPL driven development video:

seancorfield 2023-09-26T20:15:25.196539Z

What is bad-request! -- you'll need to show a bit more code. In addition, if you're getting a 500 Internal Server Error, you should see exceptions somewhere (depending on how you're starting the app).