I have a simple server running and when I try to access a POST endpoint, it doesn’t return the add-record handler, instead goes the the not-found handler. On the network tab, it actually says that the request method is a GET. What am I missing here?
Also if I curl -v http:/127.0.0.1:3000/foo , I get HTTP/1.1 404 Not Found
The GET endpoint works fine.
(ns practice.server
(:require
[compojure.core :refer [defroutes GET POST]]
[org.httpkit.server :as server]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[compojure.route :as route]))
(defn add-record
[req]
(println req))
(defn get-bar
[req]
{:status 200
:headers {"Content-Type" "text/html"}
:body "Hello World"})
(defroutes app-routes
(POST "/foo" [] add-record)
(GET "/bar" [] get-bar)
(route/not-found "Error, page not found!"))
(defn web-server
[& args]
(let [port (Integer/parseInt (or (System/getenv "PORT") "3000"))]
; Run the server with Ring.defaults middleware
(server/run-server (wrap-defaults #'app-routes site-defaults) {:port port})
(println (str "Running webserver at http:/127.0.0.1:" port "/"))))@audyarandela That is because your handler returns nil (from the println call) and Compojure treats a nil handler response as "doesn't match" and moves on to the next possible route match, which will be not-found in this case.
As soon as you make add-record return a response, it will work as you expect.
Thanks for your response! I just tried adding a simple response, same as get-bar and still was getting the same 404 error.
Oddly enough, when I change the POST route to ANY it works. But thats not REST-y and the request method on the network tab shows GET still
Are you sure you're sending a POST request with curl? I thought you needed -d to POST data...
Yes you’re correct, -d is needed for POST. getting a different error now, <h1>Invalid anti-forgery token</h1>
When trying to access it via web browser, all I was getting was that 404 error and seeing that the request method was GET, time to google some more with the new error lol
Thanks @seancorfield, I disabled the :security and :anti-forgery in site-defaults and was able to curl through. (its only a practice app to understand the tech)
Yeah, to use curl when you have CSRF in place you need to GET the form first, copy the anti-forgery token in it, then POST the form fields and the anti-forgery token.
The idea behind CSRF is that you can't just randomly POST stuff to an app -- you have to actually fill in the form fields and then submit the form. That's the security aspect of it 🙂
Yea that makes sense now lol. Probably also why the web browser showing an error because it doesn’t have the right credentials
I think you have to actually add stuff to the form so that the CSRF token is available as a hidden field... I've never used it myself (I mostly do REST APIs which use the API defaults, not the site default).
ring-defaults is good for that -- there's API, secure API, web site, and secure web site I think as four base profiles.