diff options
| author | Gabriel A. Giovanini <mail@gabrielgio.me> | 2018-02-17 13:55:55 -0200 | 
|---|---|---|
| committer | Gabriel A. Giovanini <mail@gabrielgio.me> | 2018-02-17 13:55:55 -0200 | 
| commit | 98056e815a6dcd36d7377d3cd823a4aaf5a3d9fa (patch) | |
| tree | 61f453e1b21634e0f2d740ff61091d182e145184 | |
| download | queue-api-98056e815a6dcd36d7377d3cd823a4aaf5a3d9fa.tar.gz queue-api-98056e815a6dcd36d7377d3cd823a4aaf5a3d9fa.tar.bz2 queue-api-98056e815a6dcd36d7377d3cd823a4aaf5a3d9fa.zip | |
Initial commit
| -rw-r--r-- | .gitignore | 18 | ||||
| -rw-r--r-- | Dockerfile | 8 | ||||
| -rw-r--r-- | README.md | 21 | ||||
| -rw-r--r-- | env/dev/clj/queue_api/dev_middleware.clj | 10 | ||||
| -rw-r--r-- | env/dev/clj/queue_api/env.clj | 14 | ||||
| -rw-r--r-- | env/dev/clj/user.clj | 16 | ||||
| -rw-r--r-- | env/dev/resources/config.edn | 4 | ||||
| -rw-r--r-- | env/dev/resources/logback.xml | 35 | ||||
| -rw-r--r-- | env/prod/clj/queue_api/env.clj | 11 | ||||
| -rw-r--r-- | env/prod/resources/config.edn | 2 | ||||
| -rw-r--r-- | env/prod/resources/logback.xml | 24 | ||||
| -rw-r--r-- | env/test/resources/config.edn | 4 | ||||
| -rw-r--r-- | env/test/resources/logback.xml | 35 | ||||
| -rw-r--r-- | project.clj | 66 | ||||
| -rw-r--r-- | resources/public/favicon.ico | bin | 0 -> 1150 bytes | |||
| -rw-r--r-- | src/clj/queue_api/config.clj | 12 | ||||
| -rw-r--r-- | src/clj/queue_api/core.clj | 48 | ||||
| -rw-r--r-- | src/clj/queue_api/handler.clj | 19 | ||||
| -rw-r--r-- | src/clj/queue_api/middleware.clj | 15 | ||||
| -rw-r--r-- | src/clj/queue_api/routes/services.clj | 44 | ||||
| -rw-r--r-- | test/clj/queue_api/test/handler.clj | 21 | 
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.icoBinary files differ new file mode 100644 index 0000000..0e50cb2 --- /dev/null +++ b/resources/public/favicon.ico 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)))))) | 
