Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended examples #35

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ pom.xml.asc
bower_components
*.log
/kekkonen.iml
/.idea
**/.idea
**/target
.classpath
7 changes: 7 additions & 0 deletions examples/get-post/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# get-post

A Clojure library designed to show examples of extended usage of Kekkonen.

## Usage

Use bat files provided
9 changes: 9 additions & 0 deletions examples/get-post/project.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(defproject get-post "0.1.0-SNAPSHOT"
:description "Extended examples"
:dependencies [[org.clojure/clojure "1.8.0"]
[http-kit "2.1.19"]
[clj-http "2.2.0"]
[metosin/kekkonen "0.3.0-SNAPSHOT"]]
:main get-post.core
:profiles {:dev {:dependencies [[midje "1.6.3"]
[ring-mock "0.1.5"]]}})
1 change: 1 addition & 0 deletions examples/get-post/run.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lein run
2 changes: 2 additions & 0 deletions examples/get-post/run_tests.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set MIDJE_COLORIZE=true
lein midje
2 changes: 2 additions & 0 deletions examples/get-post/run_tests_auto.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set MIDJE_COLORIZE=true
lein midje :autotest
84 changes: 84 additions & 0 deletions examples/get-post/src/get_post/core.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
(ns get-post.core
(:require [org.httpkit.server :as server]
[clj-http.client :as client]
[plumbing.core :refer [defnk]]
[kekkonen.cqrs :as cqrs]
[kekkonen.core :as k]
[schema.core :as s]))

(s/defschema GetInput
{:name s/Str
(s/optional-key :description) s/Str})

; GET http://localhost:3000/api/get-and-post?name=taras
(s/defn get-handler
"Echoes a GetInput"
[data :- GetInput]
; here is your handler
(cqrs/success data))

(s/defschema PostInput
{:data s/Str})

; POST http://localhost:3000/api/get-and-post {"data":"taras"}
(s/defn post-handler
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent 2

"Echoes a PostInput"
[data :- PostInput]
; here is your handler
(cqrs/success data))

(defnk ^:query simple-get
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent 2

"handles get"
[data request]
(cqrs/success data))

(defnk ^:get-post get-and-post
"handles both requests"
[get-params post-params request]
(if (= (:request-method request) :get)
(s/with-fn-validation (get-handler get-params))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with-fn-validation is not thread-safe

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is kekkonen.core/input-coerce! that can be used for this => uses the registered http-coercions and produces identical errors than the standard coercion.

(s/with-fn-validation (post-handler post-params))))

(defn interceptor [ctx]
"logs incoming requests for us"
(let [uri (get-in ctx [:request :uri])
request-method (name (get-in ctx [:request :request-method]))]
(println (str request-method ": " uri))
#_(clojure.pprint/pprint (:request ctx))
ctx))

(defn err-handler [ex data req]
"logs exception message and return info to client"
(println (str "ERROR: " (.getMessage ex)))
(cqrs/failure (.getMessage ex)))

(def app (cqrs/cqrs-api {:core {:handlers {:api [#'get-and-post
#'simple-get]}
:type-resolver (k/type-resolver :get-post :command :query)}
:mw {:exceptions {:handlers {:schema.core/error err-handler}}}
:ring {:types {:get-post {:methods #{:get :post}
; :query-params comes from Ring https://github.com/ring-clojure/ring/wiki/Parameters
:parameters {[:get-params] [:request :query-params]
[:post-params] [:request :body-params]}}}
:interceptors [interceptor]}}))

(defonce server (atom nil))

(defn stop-server []
(when-not (nil? @server)
(@server :timeout 100)
(reset! server nil)))

(defn -main [& args]
(reset! server (server/run-server #'app {:port 3000}))
(println "server running in port 3000")
(client/get "http://localhost:3000/api/simple-get")
(client/get "http://localhost:3000/api/get-and-post?name=taras")
(client/post "http://localhost:3000/api/get-and-post" {:body "{\"data\":\"taras\"}"
:content-type :json})
(println "Schema validation demonstration:")
(client/get "http://localhost:3000/api/get-and-post?nameWWW=taras"))

(defn run-server []
(reset! server (server/run-server #'app {:port 3000}))
(println "server running in port 3000"))
16 changes: 16 additions & 0 deletions examples/get-post/test/get_post/core_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(ns get-post.core-test
(:use midje.sweet)
(:require [clojure.test :refer :all]
[get-post.core :refer :all]
[ring.mock.request :as mock]
[kekkonen.cqrs :as cqrs]))

(facts "About http handling"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent 2

(fact "GET works for simple-get"
(app (mock/request :get "/api/simple-get?name=taras")) => cqrs/success?)
(fact "GET works for get-and-post"
(app (mock/request :get "/api/get-and-post?name=taras")) => cqrs/success?)
(fact "POST works for get-and-post"
(let [r (mock/request :post "/api/get-and-post")
rb (assoc r :body-params {:data "taras"})]
(app rb) => cqrs/success?)))