aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore18
-rw-r--r--Dockerfile8
-rw-r--r--README.md21
-rw-r--r--env/dev/clj/queue_api/dev_middleware.clj10
-rw-r--r--env/dev/clj/queue_api/env.clj14
-rw-r--r--env/dev/clj/user.clj16
-rw-r--r--env/dev/resources/config.edn4
-rw-r--r--env/dev/resources/logback.xml35
-rw-r--r--env/prod/clj/queue_api/env.clj11
-rw-r--r--env/prod/resources/config.edn2
-rw-r--r--env/prod/resources/logback.xml24
-rw-r--r--env/test/resources/config.edn4
-rw-r--r--env/test/resources/logback.xml35
-rw-r--r--project.clj66
-rw-r--r--resources/public/favicon.icobin0 -> 1150 bytes
-rw-r--r--src/clj/queue_api/config.clj12
-rw-r--r--src/clj/queue_api/core.clj48
-rw-r--r--src/clj/queue_api/handler.clj19
-rw-r--r--src/clj/queue_api/middleware.clj15
-rw-r--r--src/clj/queue_api/routes/services.clj44
-rw-r--r--test/clj/queue_api/test/handler.clj21
21 files changed, 427 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d0349ad
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+/target
+/lib
+/classes
+/checkouts
+pom.xml
+dev-config.edn
+test-config.edn
+*.jar
+*.class
+/.lein-*
+profiles.clj
+/.env
+.nrepl-port
+/log
+Procfile
+Capstanfile
+.idea/
+*.iml \ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..1580182
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,8 @@
+FROM java:8-alpine
+MAINTAINER Your Name <you@example.com>
+
+ADD target/uberjar/queue-api.jar /queue-api/app.jar
+
+EXPOSE 3000
+
+CMD ["java", "-jar", "/queue-api/app.jar"]
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..46866b8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+# queue-api
+
+generated using Luminus version "2.9.12.25"
+
+FIXME
+
+## Prerequisites
+
+You will need [Leiningen][1] 2.0 or above installed.
+
+[1]: https://github.com/technomancy/leiningen
+
+## Running
+
+To start a web server for the application, run:
+
+ lein run
+
+## License
+
+Copyright © 2018 FIXME
diff --git a/env/dev/clj/queue_api/dev_middleware.clj b/env/dev/clj/queue_api/dev_middleware.clj
new file mode 100644
index 0000000..ece7a25
--- /dev/null
+++ b/env/dev/clj/queue_api/dev_middleware.clj
@@ -0,0 +1,10 @@
+(ns queue-api.dev-middleware
+ (:require [ring.middleware.reload :refer [wrap-reload]]
+ [selmer.middleware :refer [wrap-error-page]]
+ [prone.middleware :refer [wrap-exceptions]]))
+
+(defn wrap-dev [handler]
+ (-> handler
+ wrap-reload
+ wrap-error-page
+ wrap-exceptions))
diff --git a/env/dev/clj/queue_api/env.clj b/env/dev/clj/queue_api/env.clj
new file mode 100644
index 0000000..1f31ba5
--- /dev/null
+++ b/env/dev/clj/queue_api/env.clj
@@ -0,0 +1,14 @@
+(ns queue-api.env
+ (:require [selmer.parser :as parser]
+ [clojure.tools.logging :as log]
+ [queue-api.dev-middleware :refer [wrap-dev]]))
+
+(def defaults
+ {:init
+ (fn []
+ (parser/cache-off!)
+ (log/info "\n-=[queue-api started successfully using the development profile]=-"))
+ :stop
+ (fn []
+ (log/info "\n-=[queue-api has shut down successfully]=-"))
+ :middleware wrap-dev})
diff --git a/env/dev/clj/user.clj b/env/dev/clj/user.clj
new file mode 100644
index 0000000..843b558
--- /dev/null
+++ b/env/dev/clj/user.clj
@@ -0,0 +1,16 @@
+(ns user
+ (:require
+ [mount.core :as mount]
+ [queue-api.core :refer [start-app]]))
+
+(defn start []
+ (mount/start-without #'queue-api.core/repl-server))
+
+(defn stop []
+ (mount/stop-except #'queue-api.core/repl-server))
+
+(defn restart []
+ (stop)
+ (start))
+
+
diff --git a/env/dev/resources/config.edn b/env/dev/resources/config.edn
new file mode 100644
index 0000000..6f14c22
--- /dev/null
+++ b/env/dev/resources/config.edn
@@ -0,0 +1,4 @@
+{:dev true
+ :port 3000
+ ;; when :nrepl-port is set the application starts the nREPL server on load
+ :nrepl-port 7000}
diff --git a/env/dev/resources/logback.xml b/env/dev/resources/logback.xml
new file mode 100644
index 0000000..a05ccad
--- /dev/null
+++ b/env/dev/resources/logback.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <charset>UTF-8</charset>
+ <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+ </encoder>
+ </appender>
+ <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>log/queue-api.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>log/queue-api.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100MB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ <!-- keep 30 days of history -->
+ <maxHistory>30</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <charset>UTF-8</charset>
+ <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+ </encoder>
+ </appender>
+ <logger name="org.apache.http" level="warn" />
+ <logger name="org.xnio.nio" level="warn" />
+ <logger name="io.undertow.session" level="warn" />
+ <logger name="io.undertow.request" level="warn" />
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
diff --git a/env/prod/clj/queue_api/env.clj b/env/prod/clj/queue_api/env.clj
new file mode 100644
index 0000000..c05d732
--- /dev/null
+++ b/env/prod/clj/queue_api/env.clj
@@ -0,0 +1,11 @@
+(ns queue-api.env
+ (:require [clojure.tools.logging :as log]))
+
+(def defaults
+ {:init
+ (fn []
+ (log/info "\n-=[queue-api started successfully]=-"))
+ :stop
+ (fn []
+ (log/info "\n-=[queue-api has shut down successfully]=-"))
+ :middleware identity})
diff --git a/env/prod/resources/config.edn b/env/prod/resources/config.edn
new file mode 100644
index 0000000..b48cfbd
--- /dev/null
+++ b/env/prod/resources/config.edn
@@ -0,0 +1,2 @@
+{:production true
+ :port 3000}
diff --git a/env/prod/resources/logback.xml b/env/prod/resources/logback.xml
new file mode 100644
index 0000000..3829eff
--- /dev/null
+++ b/env/prod/resources/logback.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+ <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>log/queue-api.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>log/queue-api.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100MB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ <!-- keep 30 days of history -->
+ <maxHistory>30</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <charset>UTF-8</charset>
+ <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+ </encoder>
+ </appender>
+ <logger name="org.apache.http" level="warn" />
+ <logger name="org.xnio.nio" level="warn" />
+ <root level="INFO">
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
diff --git a/env/test/resources/config.edn b/env/test/resources/config.edn
new file mode 100644
index 0000000..6f14c22
--- /dev/null
+++ b/env/test/resources/config.edn
@@ -0,0 +1,4 @@
+{:dev true
+ :port 3000
+ ;; when :nrepl-port is set the application starts the nREPL server on load
+ :nrepl-port 7000}
diff --git a/env/test/resources/logback.xml b/env/test/resources/logback.xml
new file mode 100644
index 0000000..a05ccad
--- /dev/null
+++ b/env/test/resources/logback.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <charset>UTF-8</charset>
+ <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+ </encoder>
+ </appender>
+ <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>log/queue-api.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>log/queue-api.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>100MB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ <!-- keep 30 days of history -->
+ <maxHistory>30</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <charset>UTF-8</charset>
+ <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+ </encoder>
+ </appender>
+ <logger name="org.apache.http" level="warn" />
+ <logger name="org.xnio.nio" level="warn" />
+ <logger name="io.undertow.session" level="warn" />
+ <logger name="io.undertow.request" level="warn" />
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
diff --git a/project.clj b/project.clj
new file mode 100644
index 0000000..dcc3317
--- /dev/null
+++ b/project.clj
@@ -0,0 +1,66 @@
+(defproject queue-api "0.1.0-SNAPSHOT"
+
+ :description "FIXME: write description"
+ :url "http://example.com/FIXME"
+
+ :dependencies [[clj-time "0.14.2"]
+ [compojure "1.6.0"]
+ [cprop "0.1.11"]
+ [funcool/struct "1.2.0"]
+ [luminus-immutant "0.2.4"]
+ [luminus-nrepl "0.1.4"]
+ [luminus/ring-ttl-session "0.3.2"]
+ [markdown-clj "1.0.2"]
+ [metosin/compojure-api "1.1.11"]
+ [metosin/muuntaja "0.5.0"]
+ [metosin/ring-http-response "0.9.0"]
+ [mount "0.1.11"]
+ [org.clojure/clojure "1.9.0"]
+ [org.clojure/tools.cli "0.3.5"]
+ [org.clojure/tools.logging "0.4.0"]
+ [org.webjars.bower/tether "1.4.3"]
+ [org.webjars/bootstrap "4.0.0"]
+ [org.webjars/font-awesome "5.0.6"]
+ [org.webjars/jquery "3.2.1"]
+ [ring-webjars "0.2.0"]
+ [ring/ring-core "1.6.3"]
+ [ring/ring-defaults "0.3.1"]
+ [selmer "1.11.6"]]
+
+ :min-lein-version "2.0.0"
+
+ :source-paths ["src/clj"]
+ :test-paths ["test/clj"]
+ :resource-paths ["resources"]
+ :target-path "target/%s/"
+ :main ^:skip-aot queue-api.core
+
+ :plugins [[lein-immutant "2.1.0"]
+ [lein-kibit "0.1.2"]]
+
+ :profiles
+ {:uberjar {:omit-source true
+ :aot :all
+ :uberjar-name "queue-api.jar"
+ :source-paths ["env/prod/clj"]
+ :resource-paths ["env/prod/resources"]}
+
+ :dev [:project/dev :profiles/dev]
+ :test [:project/dev :project/test :profiles/test]
+
+ :project/dev {:jvm-opts ["-server" "-Dconf=dev-config.edn"]
+ :dependencies [[pjstadig/humane-test-output "0.8.3"]
+ [prone "1.5.0"]
+ [ring/ring-devel "1.6.3"]
+ [ring/ring-mock "0.3.2"]]
+ :plugins [[com.jakemccrary/lein-test-refresh "0.19.0"]]
+
+ :source-paths ["env/dev/clj"]
+ :resource-paths ["env/dev/resources"]
+ :repl-options {:init-ns user}
+ :injections [(require 'pjstadig.humane-test-output)
+ (pjstadig.humane-test-output/activate!)]}
+ :project/test {:jvm-opts ["-server" "-Dconf=test-config.edn"]
+ :resource-paths ["env/test/resources"]}
+ :profiles/dev {}
+ :profiles/test {}})
diff --git a/resources/public/favicon.ico b/resources/public/favicon.ico
new file mode 100644
index 0000000..0e50cb2
--- /dev/null
+++ b/resources/public/favicon.ico
Binary files differ
diff --git a/src/clj/queue_api/config.clj b/src/clj/queue_api/config.clj
new file mode 100644
index 0000000..30ed9a5
--- /dev/null
+++ b/src/clj/queue_api/config.clj
@@ -0,0 +1,12 @@
+(ns queue-api.config
+ (:require [cprop.core :refer [load-config]]
+ [cprop.source :as source]
+ [mount.core :refer [args defstate]]))
+
+(defstate env
+ :start
+ (load-config
+ :merge
+ [(args)
+ (source/from-system-props)
+ (source/from-env)]))
diff --git a/src/clj/queue_api/core.clj b/src/clj/queue_api/core.clj
new file mode 100644
index 0000000..1647375
--- /dev/null
+++ b/src/clj/queue_api/core.clj
@@ -0,0 +1,48 @@
+(ns queue-api.core
+ (:require [queue-api.handler :as handler]
+ [luminus.repl-server :as repl]
+ [luminus.http-server :as http]
+ [queue-api.config :refer [env]]
+ [clojure.tools.cli :refer [parse-opts]]
+ [clojure.tools.logging :as log]
+ [mount.core :as mount])
+ (:gen-class))
+
+(def cli-options
+ [["-p" "--port PORT" "Port number"
+ :parse-fn #(Integer/parseInt %)]])
+
+(mount/defstate ^{:on-reload :noop} http-server
+ :start
+ (http/start
+ (-> env
+ (assoc :handler #'handler/app)
+ (update :io-threads #(or % (* 2 (.availableProcessors (Runtime/getRuntime)))))
+ (update :port #(or (-> env :options :port) %))))
+ :stop
+ (http/stop http-server))
+
+(mount/defstate ^{:on-reload :noop} repl-server
+ :start
+ (when-let [nrepl-port (env :nrepl-port)]
+ (repl/start {:port nrepl-port}))
+ :stop
+ (when repl-server
+ (repl/stop repl-server)))
+
+
+(defn stop-app []
+ (doseq [component (:stopped (mount/stop))]
+ (log/info component "stopped"))
+ (shutdown-agents))
+
+(defn start-app [args]
+ (doseq [component (-> args
+ (parse-opts cli-options)
+ mount/start-with-args
+ :started)]
+ (log/info component "started"))
+ (.addShutdownHook (Runtime/getRuntime) (Thread. stop-app)))
+
+(defn -main [& args]
+ (start-app args))
diff --git a/src/clj/queue_api/handler.clj b/src/clj/queue_api/handler.clj
new file mode 100644
index 0000000..97afd48
--- /dev/null
+++ b/src/clj/queue_api/handler.clj
@@ -0,0 +1,19 @@
+(ns queue-api.handler
+ (:require [compojure.core :refer [routes wrap-routes]]
+ [queue-api.routes.services :refer [service-routes]]
+ [compojure.route :as route]
+ [queue-api.env :refer [defaults]]
+ [mount.core :as mount]
+ [queue-api.middleware :as middleware]))
+
+(mount/defstate init-app
+ :start ((or (:init defaults) identity))
+ :stop ((or (:stop defaults) identity)))
+
+(mount/defstate app
+ :start
+ (middleware/wrap-base
+ (routes
+ #'service-routes
+ (route/not-found
+ "page not found"))))
diff --git a/src/clj/queue_api/middleware.clj b/src/clj/queue_api/middleware.clj
new file mode 100644
index 0000000..6d1ea43
--- /dev/null
+++ b/src/clj/queue_api/middleware.clj
@@ -0,0 +1,15 @@
+(ns queue-api.middleware
+ (:require [queue-api.env :refer [defaults]]
+ [queue-api.config :refer [env]]
+ [ring.middleware.flash :refer [wrap-flash]]
+ [immutant.web.middleware :refer [wrap-session]]
+ [ring.middleware.defaults :refer [site-defaults wrap-defaults]]))
+
+(defn wrap-base [handler]
+ (-> ((:middleware defaults) handler)
+ wrap-flash
+ (wrap-session {:cookie-attrs {:http-only true}})
+ (wrap-defaults
+ (-> site-defaults
+ (assoc-in [:security :anti-forgery] false)
+ (dissoc :session)))))
diff --git a/src/clj/queue_api/routes/services.clj b/src/clj/queue_api/routes/services.clj
new file mode 100644
index 0000000..cc8ac04
--- /dev/null
+++ b/src/clj/queue_api/routes/services.clj
@@ -0,0 +1,44 @@
+(ns queue-api.routes.services
+ (:require [ring.util.http-response :refer :all]
+ [compojure.api.sweet :refer :all]
+ [schema.core :as s]))
+
+(defapi service-routes
+ {:swagger {:ui "/swagger-ui"
+ :spec "/swagger.json"
+ :data {:info {:version "1.0.0"
+ :title "Sample API"
+ :description "Sample Services"}}}}
+
+ (context "/api" []
+ :tags ["thingie"]
+
+ (GET "/plus" []
+ :return Long
+ :query-params [x :- Long, {y :- Long 1}]
+ :summary "x+y with query-parameters. y defaults to 1."
+ (ok (+ x y)))
+
+ (POST "/minus" []
+ :return Long
+ :body-params [x :- Long, y :- Long]
+ :summary "x-y with body-parameters."
+ (ok (- x y)))
+
+ (GET "/times/:x/:y" []
+ :return Long
+ :path-params [x :- Long, y :- Long]
+ :summary "x*y with path-parameters"
+ (ok (* x y)))
+
+ (POST "/divide" []
+ :return Double
+ :form-params [x :- Long, y :- Long]
+ :summary "x/y with form-parameters"
+ (ok (/ x y)))
+
+ (GET "/power" []
+ :return Long
+ :header-params [x :- Long, y :- Long]
+ :summary "x^y with header-parameters"
+ (ok (long (Math/pow x y))))))
diff --git a/test/clj/queue_api/test/handler.clj b/test/clj/queue_api/test/handler.clj
new file mode 100644
index 0000000..1aceb3c
--- /dev/null
+++ b/test/clj/queue_api/test/handler.clj
@@ -0,0 +1,21 @@
+(ns queue-api.test.handler
+ (:require [clojure.test :refer :all]
+ [ring.mock.request :refer :all]
+ [queue-api.handler :refer :all]
+ [mount.core :as mount]))
+
+(use-fixtures
+ :once
+ (fn [f]
+ (mount/start #'queue-api.config/env
+ #'queue-api.handler/app)
+ (f)))
+
+(deftest test-app
+ (testing "main route"
+ (let [response (app (request :get "/"))]
+ (is (= 200 (:status response)))))
+
+ (testing "not-found route"
+ (let [response (app (request :get "/invalid"))]
+ (is (= 404 (:status response))))))