Web-Programmierung

Web-Programmierung

In diesem Tutorial erstellen wir eine kleine Webanwendung in Clojure mit dem HTTP-Toolkit Ring, das die Grundlage vieler Clojure-Webframeworks bildet.

Projekt anlegen

1
2
lein new app webdemo
cd webdemo

Abhängigkeiten eintragen

Öffne die Datei project.clj und ergänze unter :dependencies:

1
2
[ring/ring-core "1.11.0"]
[ring/ring-jetty-adapter "1.11.0"]

Dann:

1
lein deps

HTTP-Handler schreiben

In src/webdemo/core.clj:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(ns webdemo.core
  (:require [ring.adapter.jetty :refer [run-jetty]]))

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body "Hallo von Ring!"})

(defn -main [& args]
  (run-jetty handler {:port 3000 :join? false}))

Starten

1
lein run

Dann im Browser aufrufen:

http://localhost:3000/

Du solltest „Hallo von Ring!“ sehen.

HTML-Templates mit Selmer

Baue das Beispiel zu einer HTML-Ausgabe mit Template-Rendering aus.

Lösung

Abhängigkeit ergänzen

In project.clj:

1
[selmer "1.12.59"]

Dann:

1
lein deps

Template-Datei erstellen

Erstelle unter resources/templates/page.html:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<html>
  <head><title>{{title}}</title></head>
  <body>
    <h1>{{greeting}}</h1>
    {% if name %}
      <p>Hallo {{name}}!</p>
    {% else %}
      <p>Hallo Fremder!</p>
    {% endif %}
  </body>
</html>

Code anpassen

In src/webdemo/core.clj:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
(ns webdemo.core
  (:require [ring.adapter.jetty :refer [run-jetty]]
            [selmer.parser :as parser]))

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body (parser/render-file "templates/page.html"
                             {:title "Willkommen"
                              :greeting "Grüezi"
                              :name "Karsten"})})

(defn -main [& args]
  (parser/cache-off!) ; beim Entwickeln Templates nicht cachen
  (run-jetty handler {:port 3000}))

Test im Browser

1
lein run

Dann aufrufen: http://localhost:3000

Du solltest eine HTML-Seite mit personalisierter Begrüßung sehen.

Query-Parameter auslesen

Passe den Handler so an, dass er den Namen per URL-Query entgegennimmt.

1
http://localhost:3000/?name=Maria
Lösung

Code ändern

Damit Ring Query-Parameter wie ?name=Maria korrekt ausliest, muss eine sogenannte Middleware aktiviert werden. Ring liefert die rohe Query-Zeile zwar als :query-string, berechnet aber :query-params nur, wenn du wrap-params verwendest. Dazu definieren wir die Anwendung (app) als um handler gewrapptes Ergebnis – das ist das typische Pattern in Ring.

Die Middleware wrap-params ergänzt das Request-Map um :params und :query-params (beide als Maps mit Strings).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
(ns webdemo.core
  (:require [ring.adapter.jetty :refer [run-jetty]]
            [ring.middleware.params :refer [wrap-params]]
            [selmer.parser :as parser]))

(defn handler [request]
  (let [params (:query-params request)
        name (get params "name")]
    {:status 200
     :headers {"Content-Type" "text/html"}
     :body (parser/render-file "templates/page.html"
                               {:title "Willkommen"
                                :greeting "Grüezi"
                                :name name})}))

(def app
  (wrap-params handler))

(defn -main [& _]
  (parser/cache-off!)
  (run-jetty app {:port 3000}))

(:query-params request) enthält eine Map aller Query-Parameter als Strings.

Test im Browser

Jetzt wird der angegebene Name im Template angezeigt.

Nächste Schritte

  • Query-Parameter auslesen
  • Routing mit Compojure