Clojure file upload with hiccup, ring, compojure - clojure

I am trying to create file upload system. However, i stuck and can't resolve the problem.
My core.cjl
(ns hiccup-templating.core
(:require [compojure.core :refer [defroutes GET ANY POST]]
[compojure.route :as route]
[compojure.handler :as handler]
[ring.adapter.jetty :as jetty]
[hiccup-templating.views.layout :as layout]
[hiccup-templating.views.contents :as contents]
(ring.middleware [multipart-params :as mp])
(clojure.contrib [duck-streams :as ds])))
(defn upload-file
[file]
(ds/copy (file :tempfile) (ds/file-str (str (rand-int 30) ".jpg")))
(layout/application "Home" (contents/succes)))
(defroutes public-routes
(GET "/" [] (layout/application "Home" (contents/index)))
(mp/wrap-multipart-params
(POST "/file" {params :params} (upload-file (get params "file")))))
(def application (handler/site public-routes))
(defn -main []
(let [port (Integer/parseInt (or (System/getenv "PORT") "8080"))]
(jetty/run-jetty application {:port port :join? false})))
So i have such an error.
2017-04-25 17:00:57.934:WARN:oejs.AbstractHttpConnection:/file
java.lang.NullPointerException
at hiccup_templating.core$upload_file.invoke(core.clj:14)
at hiccup_templating.core$fn__3152.invoke(core.clj:20)
at compojure.core$make_route$fn__489.invoke(core.clj:94)
at compojure.core$if_route$fn__473.invoke(core.clj:40)
at compojure.core$if_method$fn__466.invoke(core.clj:25)
at ring.middleware.multipart_params$wrap_multipart_params$fn__947.invoke(multipart_params.clj:107)
at compojure.core$routing$fn__495.invoke(core.clj:107)
at clojure.core$some.invoke(core.clj:2443)
at compojure.core$routing.doInvoke(core.clj:107)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invoke(core.clj:619)
at compojure.core$routes$fn__499.invoke(core.clj:112)
at ring.middleware.keyword_params$wrap_keyword_params$fn__854.invoke(keyword_params.clj:32)
at ring.middleware.nested_params$wrap_nested_params$fn__903.invoke(nested_params.clj:70)
at ring.middleware.params$wrap_params$fn__820.invoke(params.clj:58)
at ring.middleware.multipart_params$wrap_multipart_params$fn__947.invoke(multipart_params.clj:107)
at ring.middleware.flash$wrap_flash$fn__2119.invoke(flash.clj:31)
at ring.middleware.session$wrap_session$fn__2099.invoke(session.clj:85)
at ring.adapter.jetty$proxy_handler$fn__2209.invoke(jetty.clj:18)
at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle(Unknown Source)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:363)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:483)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:931)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:992)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:856)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:745)
I will be glad if somebody give me the way how to understand the problem i have.

I also had this problem
Cannot find the path you want to copy the file to.
Make sure you follow the path.
I am using Linux operating system and I gave this address and the problem was solved.
(copy actual-file (File. (format "/home/naser/Desktop/%s" file-name)))

Related

How do I invoke a resolved function in a Compojure view?

I have the following code as a test:
(defn test-fn [] (println "This is a test"))
(def my-test "test")
((resolve (symbol (str my-test "-fn"))))
Which runs as I would expect producing This is a test.
So I put it inside of a separate view like so:
(ns my-test.template-views
(:require
[hiccup.core :refer :all]
[hiccup.page :refer :all]
[my-test.home-views :refer :all]
[my-test.page1-views :refer :all]))
(defn template-body
[uri]
(html5 {:lang "en"}
[:body
(let [the-page (if (> (count uri) 1)
(clojure.string/replace uri #"/" "")
"home")]
((resolve (symbol (str the-page "-body")))))]))
Which gets called from Compojure like this:
(ns the-test.reporting-dashboard
(:gen-class)
(:require
[the-test.template-views :refer :all]
[compojure.core :refer [defroutes GET POST context]]
[compojure.route :as route]
[org.httpkit.server :refer [run-server]]
))
(defn wrap-request
[handler]
(fn [request]
(let [{remote-addr :remote-addr uri :uri scheme :scheme request-method :request-method} request]
(println (str "REQUEST: " request)))
(handler request)))
(defroutes app
(wrap-request
(GET "/" request
{:status 200
:headers {"Content-Type" "text/html"}
:body (home-views/home-body (:uri request))}))
(wrap-request
(GET "/foo" request
{:status 200
:headers {"Content-Type" "text/html"}
:body (template-body (:uri request))}))
(route/resources "/")
(route/not-found {:status 404
:headers {"Content-Type" "text/html"}
:body "<h1>Not Found</h1>"}))
When I call https//mydomain.tld/foo I get a java.lang.NullPointerException:
user=> Sat Apr 24 17:59:16 MDT 2021 [worker-2] ERROR - GET /foo
java.lang.NullPointerException
at the-test.template_views$template_body.invokeStatic(template_views.clj:14)
at the-test.template_views$template_body.invoke(template_views.clj:12)
at the-test.my_test$fn__269541.invokeStatic(my_test.clj:49)
at the-test.my_test$fn__269541.invoke(my_test.clj:46)
at compojure.core$wrap_response$fn__269102.invoke(core.clj:158)
at compojure.core$wrap_route_middleware$fn__269086.invoke(core.clj:128)
at compojure.core$wrap_route_info$fn__269091.invoke(core.clj:137)
at compojure.core$wrap_route_matches$fn__269095.invoke(core.clj:146)
at the-test.my_test$wrap_request$fn__269531.invoke(my_test.clj:22)
at compojure.core$routing$fn__269110.invoke(core.clj:185)
at clojure.core$some.invokeStatic(core.clj:2705)
at clojure.core$some.invoke(core.clj:2696)
at compojure.core$routing.invokeStatic(core.clj:185)
at compojure.core$routing.doInvoke(core.clj:182)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invokeStatic(core.clj:669)
at clojure.core$apply.invoke(core.clj:662)
at compojure.core$routes$fn__269114.invoke(core.clj:192)
at org.httpkit.server.HttpHandler.run(RingHandler.java:117)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
What is going on that this function is no longer able to be called when in Compojure?
Not sure about the root cause, but I was able to find a similar, minimal example and a workaround.
I created a simple project with lein new app demo, then replaced the code for core.clj with:
(ns demo.core
(:require [clojure.string :refer :all]))
(defn -main
[& args]
(println ((resolve 'capitalize) "hello")))
Running this with lein run crashes:
$ lein run
WARNING: reverse already refers to: #'clojure.core/reverse in namespace: demo.core, being replaced by: #'clojure.string/reverse
WARNING: replace already refers to: #'clojure.core/replace in namespace: demo.core, being replaced by: #'clojure.string/replace
Syntax error (NullPointerException) compiling at (/tmp/form-init1769060018979063159.clj:1:73).
null
Full report at:
/tmp/clojure-17609112051049758700.edn
The error report shows something about an error in Compiler.java so maybe it's some lazy initialization issue or just a bug. It seems to me the var cannot be resolved at the time you are attempting to call it as a function, hence the NullPointerException.
A workaround would be to use ns-resolve instead:
(ns demo.core
(:require [clojure.string :refer :all]))
(defn -main
[& args]
(println ((ns-resolve 'clojure.string 'capitalize) "hello")))
The above works as expected:
$ lein run
WARNING: reverse already refers to: #'clojure.core/reverse in namespace: demo.core, being replaced by: #'clojure.string/reverse
WARNING: replace already refers to: #'clojure.core/replace in namespace: demo.core, being replaced by: #'clojure.string/replace
Hello
See if you can replace your usage of resolve in the view with ns-resolve if you know the namespace where the symbol needs to be looked-up.

Clojure, Compojure: How Can I add Ring middleware CORS to ring adapter jetty based project?

I am using ring adapter jetty server in my compojure api project. Now I want to add ring middleware CORS to my Project. How should I add and where should I add ring middleware CORS in my project?
These are my project code snippets
API
(ns clojure-dauble-business-api.core
(:require [compojure.api.sweet :refer :all]
[ring.util.http-response :refer :all]
[clojure-dauble-business-api.logic :as logic]
[clojure.tools.logging :as log]
[clojure-dauble-business-api.domain.artwork]
[cheshire.core :as json])
(:import [clojure_dauble_business_api.domain.artwork Artwork]))
(defapi app
(GET ["/hello/:id", :id #"[0-9]+"] [id :as request]
(log/info "Function begins from here" request)
(def jsonString (json/generate-string (get-in request [:headers])))
(log/info "Create - header value is " (get-in (json/parse-string jsonString true) [:accesstoken]))
(def artworkData (logic/artwork-id (->> id (re-find #"\d+") Long/parseLong)))
(def data (if (not-empty artworkData)
{:data artworkData :status 200}
{:data [] :status 201}))
(ok data)))
Method to Run the api on Jetty
(ns clojure-dauble-business-api.routes
(:require [compojure.core :refer :all]
[ring.adapter.jetty :as jetty]
[ring.middleware.cors :refer [wrap-cors]]
(clojure-dauble-business-api [core :as core]
[test :as t])))
(def app
(routes core/app t/test))
(jetty/run-jetty app {:port 3000})
Here core/app is the above API function path and t/test another API function(I have not provided the code here).

How to use http.kit server with drawbridge ring handler?

I have following server code:
(ns tweet-sentiment.server
(:require [clojure.java.io :as io]
[tweet-sentiment.dev :refer [is-dev? inject-devmode-html browser-repl start-figwheel start-less]]
[compojure.core :refer [GET POST defroutes]]
[compojure.route :refer [resources]]
[net.cgrand.enlive-html :refer [deftemplate]]
[net.cgrand.reload :refer [auto-reload]]
[ring.middleware.reload :as reload]
[ring.middleware.defaults :refer [wrap-defaults api-defaults]]
[tweet-sentiment.utils :refer [generate-response]]
[environ.core :refer [env]]
[org.httpkit.server :refer [run-server]]
[ring.middleware.edn :refer [wrap-edn-params]]
[tweet-sentiment.tweets :refer [tweets]]
[tweet-sentiment.dandelion :refer [dandelion-sentiment]]
[clojure.core.async :refer [>!! <!! put! take! pipe chan]]
[cemerick.drawbridge :as drawbridge]
[ring.middleware.basic-authentication :refer [wrap-basic-authentication]]
)
(:gen-class))
(defonce server (atom nil))
(deftemplate page (io/resource "index.html") []
[:body] (if is-dev? inject-devmode-html identity))
(defroutes routes
(resources "/")
(resources "/react" {:root "react"})
(GET "/*" req (page)))
(defn wrap-drawbridge [handler]
(fn [req]
(if (= "/repl" (:uri req))
(drawbridge/ring-handler req)
(handler req))))
(def http-handler
(if is-dev?
(-> #'routes
(wrap-defaults api-defaults)
reload/wrap-reload
wrap-edn-params
wrap-drawbridge)
(-> (wrap-defaults #'routes api-defaults)
wrap-edn-params
wrap-drawbridge)))
(defn run-web-server [& [port]]
(let [port (Integer. (or port (env :port) 10555))]
(println (format "Starting web server on port %d." port))
(reset! server (run-server http-handler {:port port :join? false}))))
(defn run-auto-reload [& [port]]
(auto-reload *ns*)
(start-figwheel)
(start-less))
(defn run [& [port]]
(when is-dev?
(run-auto-reload))
(run-web-server port))
(defn stop-server []
(when-not (nil? #server)
(#server :timeout 0)
(reset! server nil)))
(defn restart-server []
(stop-server)
(run-web-server))
(defn -main [& [port]]
(run port))
When I try to connect to drawbridge REPL as dev or production:
lein repl :connect http://localhost:10555/repl
I get following error:
ERROR - POST /repl
java.lang.IllegalArgumentException: No value supplied for key: {:remote-addr "127.0.0.1", :headers {"accept-encoding" "gzip, deflate", "connection" "close", "content-length" "48", "content-type" "application/x-www-form-urlencoded", "host" "localhost:10555", "user-agent" "Apache-HttpClient/4.3.3 (java 1.5)"}, :async-channel #<AsyncChannel /127.0.0.1:10555<->/127.0.0.1:60374>, :server-port 10555, :content-length 48, :websocket? false, :content-type "application/x-www-form-urlencoded", :character-encoding "utf8", :uri "/repl", :server-name "localhost", :query-string nil, :body #<BytesInputStream BytesInputStream[len=48]>, :scheme :http, :request-method :post}
at clojure.lang.PersistentHashMap.create(PersistentHashMap.java:77)
at cemerick.drawbridge$ring_handler.doInvoke(drawbridge.clj:49)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at tweet_sentiment.server$wrap_drawbridge$fn__21884.invoke(server.clj:36)
at org.httpkit.server.HttpHandler.run(RingHandler.java:91)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Problem is obviously in drawbridge/ring-handler function.
These are my dependencies:
[[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-3058" :scope "provided"]
[ring "1.3.2"]
[ring/ring-defaults "0.1.4"]
[compojure "1.3.2"]
[enlive "1.1.6"]
[org.omcljs/om "0.8.8"]
[om-sync "0.1.1"]
[environ "1.0.0"]
[http-kit "2.1.19"]
[fogus/ring-edn "0.3.0"]
[prismatic/om-tools "0.3.11"]
[secretary "1.2.3"]
[sablono "0.3.4"]
[twitter-api "0.7.8"]
[racehub/om-bootstrap "0.5.3"]
[cheshire "5.2.0"]
[com.cemerick/drawbridge "0.0.7"]
[ring-basic-authentication "1.0.1"]]
Did anybody get working http.kit server with drawbrige? What am I missing?
I eventually figured it out, server file should look somewhat like this
(ns tweet-sentiment.server
(:require [clojure.java.io :as io]
[tweet-sentiment.dev :refer [is-dev? inject-devmode-html browser-repl start-figwheel start-less]]
[compojure.core :refer [GET POST defroutes]]
[compojure.route :refer [resources]]
[net.cgrand.enlive-html :refer [deftemplate]]
[net.cgrand.reload :refer [auto-reload]]
[ring.middleware.reload :as reload]
[ring.middleware.defaults :refer [wrap-defaults api-defaults]]
[tweet-sentiment.utils :refer [generate-response]]
[environ.core :refer [env]]
[org.httpkit.server :refer [run-server]]
[ring.middleware.edn :refer [wrap-edn-params]]
[clojure.core.async :refer [>!! <!! put! take! pipe chan]]
[cemerick.drawbridge :as drawbridge]
[ring.middleware.basic-authentication :refer [wrap-basic-authentication]]
[ring.middleware.params :as params]
[ring.middleware.keyword-params :as keyword-params]
[ring.middleware.nested-params :as nested-params]
[ring.middleware.session :as session]
)
(:gen-class))
(defonce server (atom nil))
(deftemplate page (io/resource "index.html") []
[:body] (if is-dev? inject-devmode-html identity))
(defroutes routes
(resources "/")
(resources "/react" {:root "react"})
(GET "/*" req (page)))
(defn authenticated? [name pass]
(= [name pass] [(System/getenv "AUTH_USER") (System/getenv "AUTH_PASS")]))
(def drawbridge-handler
(-> (drawbridge/ring-handler)
(keyword-params/wrap-keyword-params)
(nested-params/wrap-nested-params)
(params/wrap-params)
(session/wrap-session)))
(defn http-handler [handler]
(-> handler
(wrap-defaults api-defaults)
wrap-edn-params))
(defn wrap-http [handler]
(fn [req]
(let [handler (if (= "/repl" (:uri req))
(wrap-basic-authentication drawbridge-handler authenticated?)
(if is-dev?
(-> handler
http-handler
reload/wrap-reload)
(-> handler
http-handler)))]
(handler req))))
(defn run-web-server [& [port]]
(let [port (Integer. (or port (env :port) 10555))]
(println (format "Starting web server on port %d." port))
(reset! server
(run-server (wrap-http #'routes) {:port port :join? false})
)))
(defn run-auto-reload [& [port]]
(auto-reload *ns*)
(start-figwheel)
(start-less))
(defn run [& [port]]
(when is-dev?
(run-auto-reload))
(run-web-server port))
(defn stop-server []
(when-not (nil? #server)
(#server :timeout 0)
(reset! server nil)))
(defn restart-server []
(stop-server)
(run-web-server))
(defn -main [& [port]]
(run port))

Getting started with liberator

I am new to clojure and liberator.
I am trying to get started with liberator but I am stuck on the following error.
Here is my code that starts the webserver and defines the routes:
(ns game-of-life.core
(:require
[ring.util.response :as resp]
[compojure.route :as route]
[ring.adapter.jetty :as jetty])
(:use
[ring.middleware.multipart-params :only [wrap-multipart-params]]
[ring.util.response :only [header]]
[compojure.core :only [context ANY routes defroutes]]
[compojure.handler :only [api]]))
(defn assemble-routes []
(->
(routes
(ANY "/" [] (resp/redirect "/index.html"))
(route/resources "/"))))
(def handler
(-> (assemble-routes))
(defn start [options]
(jetty/run-jetty #'handler (assoc options :join? false)))
(defn -main
([port]
(start {:port (Integer/parseInt port)}))
([]
(-main "3000")))
When I run lein ring server, I get a java.lang.NullPointerException with the following stacktrace:
reload.clj:18 ring.middleware.reload/wrap-reload[fn]
stacktrace.clj:17 ring.middleware.stacktrace/wrap-stacktrace-log[fn]
stacktrace.clj:80 ring.middleware.stacktrace/wrap-stacktrace-web[fn]
jetty.clj:18 ring.adapter.jetty/proxy-handler[fn] (Unknown
Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle
HandlerWrapper.java:116 org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:363 org.eclipse.jetty.server.Server.handle
AbstractHttpConnection.java:483 org.eclipse.jetty.server.AbstractHttpConnection.handleRequest
AbstractHttpConnection.java:920 org.eclipse.jetty.server.AbstractHttpConnection.headerComplete
AbstractHttpConnection.java:982 org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete
HttpParser.java:635 org.eclipse.jetty.http.HttpParser.parseNext
HttpParser.java:235 org.eclipse.jetty.http.HttpParser.parseAvailable
AsyncHttpConnection.java:82 org.eclipse.jetty.server.AsyncHttpConnection.handle
SelectChannelEndPoint.java:628 org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle
SelectChannelEndPoint.java:52 org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run
QueuedThreadPool.java:608 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
QueuedThreadPool.java:543 org.eclipse.jetty.util.thread.QueuedThreadPool$3.run
Thread.java:744 java.lang.Thread.run
I think it will work better if your handler function get the request argument.
Can you try changing the dependencies like this? These versions and the following config totally works for me: (including reloading)
(defproject ..........
:dependencies [[org.clojure/clojure "1.5.1"]
[liberator "0.11.0"]
[ring/ring-core "1.1.8"]
[ring/ring-jetty-adapter "1.1.8"]
[compojure "1.1.3"]]
:main game-of-life.core
:min-lein-version "2.0.0"
:plugins [[lein-ring "0.8.10"]]
:ring {:handler game-of-life.core/handler})
Plus the handler should be
(def handler
(-> (assemble-routes)))

Compojure app not playing well with with-redefs

I'm writing a Compojure application and am using clj-webdriver to graphically test it. I'm trying to use with-redefs to mock out the function that pulls out data from persistence to just return canned values, but it's ignoring my function overwrite. I know with-redefs works in terms of vars, but it's still not working:
project.clj relevant pieces:
(defproject run-hub "0.1.0-SNAPSHOT"
:main run-hub.handler/start-server)
handler.clj:
(ns run-hub.handler
(:require [compojure.core :refer :all]
[compojure.handler :as handler]
[compojure.route :as route]
[ring.adapter.jetty :refer :all]
[run-hub.controllers.log-controller :as log-controller]))
(defroutes app-routes
(GET "/MikeDrogalis/log" [] (log-controller/mikes-log))
(route/resources "/")
(route/not-found "Not Found"))
(def app (handler/site #'app-routes))
log-controller.clj:
(ns run-hub.controllers.log-controller
(:require [run-hub.views.log :as views]
[run-hub.persistence :as persistence]))
(defn mikes-log []
(views/mikes-log (persistence/mikes-log)))
persistence.clj
(ns run-hub.persistence
(require [clj-time.core :as time]
[run-hub.models.log :as log]))
(defn mikes-log [] [])
And finally, my graphical test - which tries to override mikes-log and fails:
(fact
"It has the first date of training as August 19, 2012"
(with-redefs [persistence/mikes-log (fn [] (one-week-snippet))]
(to (local "/MikeDrogalis/log"))
(.contains (text "#training-log") "August 19, 2012"))
=> true)
Where one-week-snippet is a function that returns some sample data.
(defn start-server []
(run-jetty (var app) {:port 3000 :join? false}))
I am able to use with-redefs in a clj-webdriver test doing the following:
(defn with-server
[f]
(let [server (run-jetty #'APP {:port 0 :join? false})
port (-> server .getConnectors first .getLocalPort)]
(binding [test-port port]
(try
(println "Started jetty on port " test-port)
(f)
(finally
(.stop server))))))
(use-fixtures :once with-server)
Then the whole bunch of tests gets its own jetty and this seems to run in
such a manner that with-redefs works.