Redirect in a SPA on the server side.

1,072 views
Skip to first unread message

Hari Krishnan

unread,
Sep 11, 2015, 11:34:58 PM9/11/15
to ClojureScript
Hello All,


I am working on a use case as follows: The UI is with reagent, re-frame for subscription & Luminus, and for the backend, I use Compojure. I also tried with Liberator, but for simplicity, I am using only Compojure now.

I also use Secretary & cljs-ajax for SPA routing and ajax.

-> User brings up "/person" URL, and use a set of actions. The page data is sent to the backend, gets validated and saved to the DB. Then the user has to be re-directed to "/job". If there is any error, the errors will be displayed on the "/person" page.

There are two application components -- one with the URL "/person",and the other with "/job". With each of these, I have a few related pages, and I am creating them as SPA with Reagent.

The question is how do I redirect to the "/job"?

Client Side Code (only the the relevant ones)

(POST "/person"
{:headers {"Accept" "application/clojure"}
:params @doc

:handler ex-handler
:error-handler ex-error-handler})

Server:
(defn process-person []
(-> (redirect "/job" :permanent)
(header "Content-Type" "text/html; charset=utf-8")
(header "Location" "/job")
)
)

(POST "/person" [params] (process-person params))

Interestingly, on the console, I can see the HTML for the "job" page. Do I have to change the Secretary code to make it happen?

Any help is much appreciated.

Regards,
Hari

Val Waeselynck

unread,
Sep 12, 2015, 9:19:41 AM9/12/15
to ClojureScript
Because you're working with AJAX, you do not want your server to redirect. You want to just send the data to the server, and then change the URL of the page with something like

window.location.href = <job-page-url>

Hari Krishnan

unread,
Sep 12, 2015, 2:56:30 PM9/12/15
to ClojureScript
Hi Val,

Thanks for the answer. I still have one more issue related to this logic. When I set the :location at the header onn the server side, what I see on the client console (Chrome) is as follows (logging the response from the server): I don't see the location key/value, instead, I see the whole page in HTML. Any hint? tried with different doc-types.

{:status 200,
:success true,
:body "<!DOCTYPE html>\r\n<html>\r\n\r\n<head>\r\n <!-- Meta, title, CSS, favicons, etc. -->\r\n <meta charset=\"utf-8\">\r\n <title>----------</html>\r\n",

:headers {"date" "Sat, 12 Sep 2015 18:27:30 GMT", "x-content-type-options" "nosniff", "server" "undertow", "x-frame-options" "SAMEORIGIN", "content-type" "text/html; charset=utf-8", "connection" "keep-alive", "content-length" "3928", "x-xss-protection" "1; mode=block"},
:trace-redirects ["/person" "/person"],
:error-code :no-error,
:error-text ""}

(defresource post-person-resource
:available-media-types [ "application/clojure"]
:allowed-methods [:post]
:post! (fn [context] ())
:post-redirect? (fn [ctx] {:location "/job"})

ON THE Client side, I solved the redirect issue with the following code:

(.assign js/location "/job")

But I couln't find the location in the header. So I hard-coded it here!

Thanks for the response.

Regards,
Hari

Val Waeselynck

unread,
Sep 12, 2015, 3:33:18 PM9/12/15
to ClojureScript
This is how HTTP works. What you're seeing is the "target" response of the redirection, not the "redirect" response (which has a 301 status code and a "Location" header).

Again, this weird hybridation of classical web pages / AJAX behavior is probably the root of all evil here :). IMO the way to go here is to not redirect from the server, this is a decision to be made by the client (and your client knowing why it fetched the data, it probably also knows where to go next :) ).

Hari Krishnan

unread,
Sep 12, 2015, 4:34:13 PM9/12/15
to ClojureScript
Hi Val,

Got it. Thanks for the response. A good guideline. I needed that validation.

Regards,
Hari
Reply all
Reply to author
Forward
0 new messages