Last active
March 10, 2022 12:24
-
-
Save drbobbeaty/e580eba3e13a799b91c1 to your computer and use it in GitHub Desktop.
Simple clojure Ring example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns performance.server | |
"The routes for the web server." | |
(:require [cheshire.core :as json] | |
[clj-time.core :refer [now]] | |
[clojure.tools.logging :refer [infof warn warnf error errorf]] | |
[compojure | |
[core :refer [defroutes GET POST]] | |
[handler :as handler]] | |
[ring.middleware.jsonp :refer [wrap-json-with-padding]] | |
[ring.middleware.params :refer [wrap-params]] | |
[ring.util.io :refer [piped-input-stream]]) | |
(:import [java.io BufferedWriter OutputStreamWriter])) | |
;; extend cheshire to allow for the encoding of Joda DateTime values... | |
(extend-protocol cheshire.generate/JSONable | |
org.joda.time.DateTime | |
(to-json [t jg] | |
(cheshire.generate/write-string jg (str t)))) | |
(defn safe-parse-json | |
"Function to attempt to parse a JSON string from the user - and we have to be | |
VERY careful about this, as we have NO trust in this user - so check for all | |
possible problems, and if it's invalid JSON, return a nil." | |
[s] | |
(cond | |
(or (empty? s) (not (string? s))) nil | |
:else (try | |
(json/parse-string s true) | |
(catch com.fasterxml.jackson.core.JsonParseException jpe | |
(warnf "JSON parse exception on: %s => %s" s (.getMessage jpe)) | |
nil)))) | |
(defn return-code | |
"Creates a ring response for returning the given return code." | |
[code] | |
{:status code | |
:headers {"Content-Type" "application/json; charset=UTF-8"}}) | |
(defn return-json | |
"Creates a ring response for returning the given object as JSON." | |
([ob] (return-json ob (now) 200)) | |
([ob lastm] (return-json ob lastm 200)) | |
([ob lastm code] | |
{:status code | |
:headers {"Content-Type" "application/json; charset=UTF-8" | |
"Last-Modified" (str (or lastm (now)))} | |
;; TODO: the input-stream tactic is foiled by ring.middleware.jsonp | |
;; which slurps the whole stream before adding the callback. Could | |
;; fix by patching that lib. We should still be getting the benefit | |
;; for the non-browser case though. | |
:body (piped-input-stream | |
(fn [out] | |
(->> out | |
(OutputStreamWriter.) | |
(BufferedWriter.) | |
(json/generate-stream ob))))})) | |
(defroutes app-routes | |
"Primary routes for the webserver." | |
(GET "/" [] | |
(return-json {:app "performance", | |
:hello? "World!", | |
:code (or (git-commit) "unknown commit")})) | |
(POST "/v1/deals_performance.json" [:as {body :body}] | |
(let [deals (json/parse-json (slurp body))] | |
(cond | |
(empty? deals) (return-code 400) | |
(not (coll? deals)) (return-code 400) | |
:else | |
(return-json deals))))) |
@fuzzyami The benefit is for Services calling this Service - in a SOA scheme. In browsers, it's possible to have unpredictable users do things like close the tab, and break the streaming of the data before it's complete. A Service making the call wouldn't likely do that, so we get the benefits of Streaming without having to fix the underlying JSONP code.
This was all done primarily for Service-to-Service communication - not Client-to-Service.
That was super quick. thank you!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hola! could you please elaborate on
We should still be getting the benefit for the non-browser case though.
what's the benefit? what's the non-browser case? thx!