### Install Dependencies for Pedestal Source: https://pedestal.io/pedestal/0.8/contributing.html Run this command from the root directory for the initial setup, especially for versions not yet uploaded to Clojars. Failure to do so may result in ClassNotFoundException during testing. ```bash clj -T:build install ``` -------------------------------- ### Implement Pedestal Component Start Method Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Implements the 'start' method for the Pedestal component, initializing and starting the Pedestal connector with specified interceptors and routes. ```clojure (start [this] (assoc this :connector (-> (conn/default-connector-map 8890) (conn/with-interceptor (inject-components components)) (conn/optionally-with-dev-mode-interceptors) (conn/with-default-interceptors) (conn/with-routes app.routes/routes) (hk/create-connector nil) (conn/start!)))) ``` -------------------------------- ### Start Service Directly Source: https://pedestal.io/pedestal/0.8/guides/embedded-template.html Use this command to start the service without an interactive REPL. The service will log startup information to the console. ```bash $ clj -X:run INFO com.blueant.peripheral.main - {:msg "Service com.blueant/peripheral startup", :port 8080, :line 10} ``` -------------------------------- ### Start Pedestal Service Source: https://pedestal.io/pedestal/0.8/guides/hello-world-query-parameters.html Starts the Pedestal service by requiring the 'hello' namespace and calling the 'start' function. The REPL will print the created connector object. ```shell $ clj Clojure 1.12.0 user=> (require 'hello) nil user=> (hello/start) #object[io.pedestal.http.http_kit$create_connector$reify__15862 0x3b85a820 "io.pedestal.http.http_kit$create_connector$reify__15862@3b85a820"] user=> ``` -------------------------------- ### Start Pedestal Service Source: https://pedestal.io/pedestal/0.8/guides/your-first-api.html Starts the Pedestal HTTP service from the REPL. This command requires the 'main' namespace to be loaded. ```bash $ clj Clojure 1.12.0 user=> (require 'main) nil user=> (main/start) #object[io.pedestal.http.http_kit$create_connector$reify__15862 0x63cd8f26 "io.pedestal.http.http_kit$create_connector$reify__15862@63cd8f26"] user=> ``` -------------------------------- ### Project Setup Commands Source: https://pedestal.io/pedestal/0.8/guides/your-first-api.html Commands to create a new project directory and its source folder. ```bash $ mkdir todo-api $ cd todo-api $ mkdir src ``` -------------------------------- ### Reload and Start Application Namespace Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html Reloads the 'hello' namespace to incorporate changes from the source file and then starts the application's HTTP server. ```clojure (require :reload 'hello) nil (hello/start) ``` -------------------------------- ### Create and Start Connector Source: https://pedestal.io/pedestal/0.8/guides/sse.html Defines functions to create, start, stop, and restart the Pedestal connector, including the SSE routes. ```clojure (defn create-connector [] (-> (conn/default-connector-map 8890) (conn/with-default-interceptors) (conn/with-routes routes) (hk/create-connector nil))) (defonce *connector (atom nil)) (defn start [] (reset! *connector (conn/start! (create-connector)))) (defn stop [] (conn/stop! @*connector) (reset! *connector nil)) (defn restart [] (when @*connector (stop)) (start)) ``` -------------------------------- ### Pedestal Request Log Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html Example log output from Pedestal showing an incoming GET request to the '/greet' path. ```clojure [] INFO io.pedestal.service.interceptors - {:msg "GET /greet", :line 40} ``` -------------------------------- ### Start Development Server with REPL Source: https://pedestal.io/pedestal/0.8/guides/embedded-template.html Launch a REPL and start the service in development mode using the :test and :dev-mode aliases. The :dev-mode alias enables features like routing table printing and hot reloading. ```clojure $ clj -A:test:dev-mode __**(1)** Clojure 1.12.0 user=> (use 'dev) nil user=> (go!) Routing table: ┌──────┬──────┬────────────────────────────────────────────┐ │Method│ Path │ Name │ ├──────┼──────┼────────────────────────────────────────────┤ │ :get│/*path│:io.pedestal.service.resources/get-resource │ │ :head│/*path│:io.pedestal.service.resources/head-resource│ │ :get│/hello│:com.blueant.peripheral.routes/hello │ │ :post│/hello│:com.blueant.peripheral.routes/greet │ └──────┴──────┴────────────────────────────────────────────┘ #object[io.pedestal.http.http_kit$create_connector$reify__17907 0x6e3f108c "io.pedestal.http.http_kit$create_connector$reify__17907@6e3f108c"] user=> ``` -------------------------------- ### Create Project Directory Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html Set up the project structure by creating and navigating into a new directory for your Pedestal application. This is the first step in starting from scratch. ```bash $ mkdir hello-world $ cd hello-world ``` -------------------------------- ### Example Project Creation Output Source: https://pedestal.io/pedestal/0.8/guides/embedded-template.html Demonstrates the directory structure of a newly created Pedestal embedded project. The exact files may vary as the template evolves. ```bash $ clojure -Tnew create :template io.github.pedestal/pedestal%embedded%io.pedestal/embedded#0.8.2-beta-5 :name com.blueant/peripheral Resolving io.github.pedestal/pedestal as a git dependency Creating project from io.pedestal/embedded in peripheral $ tree peripheral ├── build.clj ├── CHANGELOG.md ├── deps.edn ├── dev │   ├── com │   │   └── blueant │   │   └── peripheral │   │   └── telemetry_test_init.clj │   ├── dev.clj │   └── user.clj ├── doc │   └── intro.md ├── LICENSE ├── README.md ├── resources │   ├── logback.xml │   ├── pedestal-config.edn │   └── public │   ├── app.css │   ├── index.html │   └── pedestal-glyph.png ├── src │   └── com │   └── blueant │   └── peripheral │   ├── connector.clj │   ├── main.clj │   ├── routes.clj │   └── telemetry_init.clj ├── start-jaeger.sh ├── test │   └── com │   └── blueant │   └── peripheral │   └── connector_test.clj └── test-resources ├── logback-test.xml └── pedestal-test-config.edn 17 directories, 22 files > ``` -------------------------------- ### Reference Alias for REPL Session Source: https://pedestal.io/pedestal/0.8/reference/config.html Start a REPL session using a defined alias in `deps.edn` to apply associated JVM options. This example references the `:dev-mode` alias. ```bash clj -A:dev-mode ... ``` -------------------------------- ### Install deps-new Tool Source: https://pedestal.io/pedestal/0.8/guides/embedded-template.html Installs the latest version of the `deps-new` tool. This is a prerequisite for generating new projects from templates. ```bash clojure -Ttools install-latest :lib io.github.seancorfield/deps-new :as new ``` -------------------------------- ### Query Parameters Example 1 Source: https://pedestal.io/pedestal/0.8/reference/parameters.html Demonstrates how a simple query parameter is parsed and attached to the request map. ```clojure /path/to/resource?after=123123%2099 ``` ```clojure {:after "123123 99"} ``` -------------------------------- ### Create and Start Pedestal Connector Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html Defines functions to create a Pedestal connector with specified routes and interceptors, and then starts the connector. The `->` macro chains function calls for concise configuration. ```clojure (defn create-connector [] (-> (conn/default-connector-map 8890) __**(1)** (conn/with-default-interceptors) __**(2)** (conn/with-routes routes) __**(3)** (hk/create-connector nil))) __**(4)** (defn start [] (conn/start! (create-connector))) __**(5)** ``` -------------------------------- ### Start Pedestal Application Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Starts the Pedestal application in development mode using the clj tool. The :test alias adds test dependencies, and :dev-mode enables development features like route table printing. ```bash $ clj -A:test:dev-mode ``` ```clojure user=> (start!) ``` -------------------------------- ### Start, Stop, and Restart Connector Source: https://pedestal.io/pedestal/0.8/guides/your-first-api.html Defines functions to manage the lifecycle of a connector. Ensure the connector is started before use and stopped cleanly. ```clojure (defonce *connector (atom nil)) (defn start [] (reset! *connector __**(2)** (conn/start! (create-connector)))) (defn stop [] (conn/stop! @*connector) (reset! *connector nil)) (defn restart [] __**(3)** (stop) (start)) ``` -------------------------------- ### Start REPL in Development Mode Source: https://pedestal.io/pedestal/0.8/guides/live-repl.html Launch your Clojure REPL using the `clj` tool with the `:dev` alias to activate development mode. ```bash clj -A:dev ``` -------------------------------- ### Check Java Version Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html Verify that Java is installed and its version is at least 11. This is a prerequisite for running Pedestal applications. ```bash $ java -version ``` -------------------------------- ### HTTP Request and Response Example Source: https://pedestal.io/pedestal/0.8/guides/war-deployment.html This example shows a typical HTTP request and response when running an application inside a WAR file with Jetty. The response includes headers provided by default interceptors. ```http < HTTP/1.1 200 OK < Server: Jetty(12.0.22) < Strict-Transport-Security: max-age=31536000; includeSubdomains < X-Frame-Options: DENY < X-Content-Type-Options: nosniff < X-XSS-Protection: 1; mode=block < X-Download-Options: noopen < X-Permitted-Cross-Domain-Policies: none < Content-Security-Policy: object-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:; < Content-Type: text/plain < Transfer-Encoding: chunked < * Connection #0 to host localhost left intact Greetings from inside the WAR file. $ ``` -------------------------------- ### Complete Hello World Application Code Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html The full source code for the 'hello' namespace, including namespace definition, dependencies, handler function, routes, and connector setup. ```clojure (ns hello __**(1)** (:require [io.pedestal.connector :as conn] __**(2)** [io.pedestal.http.http-kit :as hk])) __**(3)** (defn greet-handler [_request] __**(1)** {:status 200 :body "Hello, world!\n"}) __**(2)** (def routes #{["/greet" :get greet-handler :route-name :greet]}) (defn create-connector [] (-> (conn/default-connector-map 8890) __**(1)** (conn/with-default-interceptors) __**(2)** (conn/with-routes routes) __**(3)** (hk/create-connector nil))) __**(4)** (defn start [] (conn/start! (create-connector))) __**(5)**) ``` -------------------------------- ### Start Service with Open Telemetry Agent Source: https://pedestal.io/pedestal/0.8/guides/embedded-template.html This command starts a new REPL session with the Open Telemetry Java Agent enabled via the `:otel-agent` alias. This agent instruments the application to capture request and response times for tracing. ```bash $ clj -A:test:otel-agent OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended [otel.javaagent 2025-03-27 16:12:48:691 -0700] [main] INFO io.opentelemetry.javaagent.tooling.VersionLogger - opentelemetry-javaagent - version: 2.14.0 Clojure 1.12.0 user=> (use 'dev) nil user=> (go!) #object[io.pedestal.http.http_kit$create_connector$reify__17973 0x16a475d3 "io.pedestal.http.http_kit$create_connector$reify__17973@16a475d3"] user=> ``` -------------------------------- ### Curl Examples with Query Parameters Source: https://pedestal.io/pedestal/0.8/guides/hello-world-query-parameters.html Demonstrates various ways to use curl to send requests with different query parameters, including Unicode and URL-encoded spaces. ```bash $ curl http://localhost:8890/greet\?name=Michael Hello, Michael ``` ```bash $ curl http://localhost:8890/greet\?name=Pankaj Hello, Pankaj ``` ```bash $ curl http://localhost:8890/greet\?name=Geeta Hello, Geeta ``` ```bash $ curl http://localhost:8890/greet\?name=ไอรีนซีพีชาไอที __**(1)** Hello, ไอรีนซีพีชาไอที ``` ```bash $ curl http://localhost:8890/greet\?name=No%20One%20To%20Be%20Trifled%20With __**(2)** Hello, No One To Be Trifled With ``` ```bash $ curl http://localhost:8890/greet\?name= Hello, ``` ```bash $ curl http://localhost:8890/greet Hello, ``` -------------------------------- ### Define Routes for GET /greet Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Maps the /greet URL to the GET HTTP method and the get-greeting handler. Routes are defined as a set of vectors. ```clojure (def routes #{["/greet" :get get-greeting :route-name :greet]}) ``` -------------------------------- ### Query Parameters Example 2 Source: https://pedestal.io/pedestal/0.8/reference/parameters.html Illustrates parsing of multiple query parameters, including those with special characters and potential keyword-like names. ```clojure /path/to/resource?after:page=12&after:storyid=abc123XYZ&user%20id=99 ``` ```clojure {:after:page "12" :after:storyid "abc123XYZ" :user id "99"} ``` -------------------------------- ### Expand Routes Example Source: https://pedestal.io/pedestal/0.8/reference/routing-quick-reference.html Demonstrates how to use `expand-routes` to convert route specifications into a routing table. Supports a mix of data formats and direct function calls. ```clojure (:routes (route/expand-routes #{{:app-name :example-app :scheme :https :host "example.com"} ["/department/:id/employees" :get [...] :route-name :org.example.app/employee-search :constraints {:name #".+" :order #"(asc|desc)"}]})) ``` -------------------------------- ### Wildcard Path Parameter Example Source: https://pedestal.io/pedestal/0.8/reference/routing-quick-reference.html Shows how to use a wildcard path parameter (prefixed with `*`) to capture multiple path segments. This is typically used at the end of a path. ```clojure ["/accounts/*ids" :get …​] ``` -------------------------------- ### Define a GET Route for /greet Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html This snippet defines a single route that matches a GET request to the /greet path and maps it to the greet-handler function. Ensure that the greet-handler is defined elsewhere and adheres to the contract of accepting a request map and returning a response map. ```clojure (def routes #{["/greet" :get greet-handler :route-name :greet]}) ``` -------------------------------- ### Sample Logging Output Format Source: https://pedestal.io/pedestal/0.8/reference/logging.html Example of how log events are formatted, including the log level, namespace, and the Clojure map containing event data, :in, :user-id, :roles, and :line. ```text DEBUG org.example.routes - {:in auth, :user-id "3d1535dd-18fa-40f1-95f8-78d7f44b0319", :roles #{"buyer" "admin" "manager"}, :line 37} ``` -------------------------------- ### User Namespace for System Management Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Sets up a user namespace for REPL-driven development, including functions to start and stop the application system. It utilizes clj-reload for hot-reloading. ```clojure (ns user (:require [com.stuartsierra.component :as component] clj-reload.core app.system)) (defonce *system (atom nil)) (defn start! [] (reset! *system (-> (app.system/new-system) (component/start-system)))) (defn stop! [] (when-let [system @*system] (component/stop-system system)) (reset! *system nil)) ``` -------------------------------- ### Formatted Request Map Example Source: https://pedestal.io/pedestal/0.8/guides/hello-world-query-parameters.html A formatted and simplified view of the request map received by the server, highlighting key fields like :query-string and :query-params. ```clojure { :request-method :get :uri "/greet" :query-string "name=Michael" :query-params {:name "Michael"} :params {:name "Michael"} :headers {"accept" "*/*" "host" "localhost:8890" "user-agent" "curl/8.7.1"} :remote-addr "127.0.0.1" :server-port 8890 :content-length 0 :content-type nil :path-info "/greet" :character-encoding "utf8" :server-name "localhost" :path-params {} :body nil :scheme :http} ``` -------------------------------- ### Create HTTP Connector Source: https://pedestal.io/pedestal/0.8/guides/your-first-api.html Configures and creates the HTTP connector using http-kit. It sets up default interceptors, applies the defined routes, and starts the connector on port 8890. ```clojure (defn create-connector [] (-> (conn/default-connector-map 8890) (conn/with-default-interceptors) (conn/with-routes routes) (hk/create-connector nil))) ``` -------------------------------- ### Testing the Deployed Application Source: https://pedestal.io/pedestal/0.8/guides/war-deployment.html Use curl to send a GET request to the deployed application's '/hello' endpoint on localhost:8080. This verifies that the WAR file has been successfully deployed and is accessible. ```bash $ curl -v localhost:8080/hello * Host localhost:8080 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:8080... * Connected to localhost (::1) port 8080 > GET /hello HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/8.7.1 > Accept: */* > ``` -------------------------------- ### Basic Greeting Test Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Tests the `GET /api/greet` endpoint to ensure it returns a 200 status and the expected greeting message using the `with-system` macro and `response` helper. ```clojure (deftest greeting-test (with-system [system (app.system/new-system)] __**(1)** (is (match? __**(2)** {:status 200 :body "Greetings for the 1st time\n"} (response system :get "/api/greet"))) __**(3)** )) ``` -------------------------------- ### Start a Basic Pedestal Application Source: https://pedestal.io/pedestal/0.8/index.html This snippet demonstrates how to set up a minimal Pedestal application that listens on port 8080 and responds with 'Hello, world!' to requests on the '/greet' path. It requires importing the necessary Pedestal connector and HTTP-Kit libraries. ```clojure (ns front-page (:require [io.pedestal.connector :as conn] [io.pedestal.http.http-kit :as hk])) (defn- greet-handler [_request] {:status 200 :body "Hello, world!"}) (defn start! [] (-> (conn/default-connector-map 8080) (conn/with-default-interceptors) (conn/with-routes #{["/greet" :get greet-handler]}) (hk/create-connector nil) (conn/start!))) ``` -------------------------------- ### Curl Request to Echo Endpoint Source: https://pedestal.io/pedestal/0.8/guides/hello-world-content-types.html Example of using curl to send a GET request to the /echo endpoint, demonstrating the interceptor's functionality. ```bash $ curl http://localhost:8890/echo ``` -------------------------------- ### Timing Interceptor Example Source: https://pedestal.io/pedestal/0.8/guides/what-is-an-interceptor.html This interceptor measures the time taken to process a request and logs the elapsed time. It adds the start time to the context and removes it after execution. ```clojure (def timing-interceptor (interceptor {:name ::timing __**(1)** :enter (fn [context] (assoc context ::start-ms (System/currentTimeMillis))) __**(2)** :leave (fn [context] (let [{::keys [start-ms]} context __**(3)** elapsed-ms (- (System/currentTimeMillis) start-ms)] (log/debug :elapsed-ms elapsed-ms) __**(4)** (dissoc context ::start-ms)))})) __**(5)** ``` -------------------------------- ### Start Clojure REPL and Download Dependencies Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html Initiate the Clojure REPL using the `clj` command. This will automatically download necessary dependencies if they are not already cached. Downloads occur only on the first run. ```bash $ clj Downloading: io/pedestal/pedestal.jetty/0.8.0/pedestal.jetty-0.8.0.pom from clojars Downloading: io/pedestal/pedestal.service/0.8.0/pedestal.service-0.8.0.pom from clojars Downloading: io/pedestal/pedestal.log/0.8.0/pedestal.log-0.8.0.pom from clojars ... Clojure 1.12 user=> ``` -------------------------------- ### Test Initial Route Source: https://pedestal.io/pedestal/0.8/guides/live-repl.html Use the `http` CLI tool to send a request to the `/hello` endpoint and verify the initial response. ```bash > http -pb :9999/hello Hello, World! ``` -------------------------------- ### Run Pedestal Application with clj Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-ssl.html Use the `clj` tool with the `:run` alias to start the Pedestal application. This command initiates the system, and the output shows server startup logs, including details about SSL configuration. ```bash $ clj -M:run ``` ```log [main] INFO org.eclipse.jetty.server.Server - jetty-12.0.22; built: 2025-06-02T15:25:31.946Z; git: 335c9ab44a5591f0ea941bf350e139b8c4f5537c; jvm 21.0.4+7-LTS [main] INFO org.eclipse.jetty.session.DefaultSessionIdManager - Session workerName=node0 [main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started oeje10s.ServletContextHandler@16c2da2c{ROOT,/,b=null,a=AVAILABLE,h=oeje10s.SessionHandler@94b4ce6{STARTED}} [main] INFO org.eclipse.jetty.ee10.servlet.ServletContextHandler - Started oeje10s.ServletContextHandler@16c2da2c{ROOT,/,b=null,a=AVAILABLE,h=oeje10s.SessionHandler@94b4ce6{STARTED}} [main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@8f340ff{HTTP/1.1, (http/1.1, h2c)}{127.0.0.1:8080} [main] INFO org.eclipse.jetty.util.ssl.SslContextFactory - x509=X509@57f7590f(1,h=[yourservername.com, localhost, 127.0.0.1],a=[]) for Server@3255707f[provider=null,keyStore=file:///.../server.p12,trustStore=null] [main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@e01664e{SSL, (ssl, http/1.1)}{127.0.0.1:8443} [main] INFO org.eclipse.jetty.server.Server - Started oejs.Server@43f41fe0{STARTING}[12.0.22,sto=0] @4047ms ``` -------------------------------- ### Complete Hello World Application with Query Parameters Source: https://pedestal.io/pedestal/0.8/guides/hello-world-query-parameters.html This snippet includes the full Clojure code for a Pedestal application that handles a '/greet' route, extracts a 'name' query parameter, and returns a personalized greeting or a 'not found' response. ```clojure (ns hello (:require [io.pedestal.connector :as conn] [io.pedestal.http.http-kit :as hk])) (def unmentionables #{"YHWH" "Voldemort" "Mxyzptlk" "Rumplestiltskin" "曹操"}) (defn ok [message] {:status 200 :body message}) (defn not-found [] {:status 404 :body "Not found\n"}) (defn greeting-for [greet-name] (cond (unmentionables greet-name) nil (empty? greet-name) "Hello, world!\n" :else (str "Hello, " greet-name "\n"))) (defn greet-handler [request] (let [greet-name (get-in request [:query-params :name]) message (greeting-for greet-name)] (if message (ok message) (not-found)))) (def routes #{["/greet" :get greet-handler :route-name :greet]}) (defn create-connector [] (-> (conn/default-connector-map 8890) (conn/with-default-interceptors) (conn/with-routes routes) (hk/create-connector nil))) ;; For interactive development (defonce *connector (atom nil)) (defn start [] (reset! *connector (conn/start! (create-connector)))) (defn stop [] (conn/stop! @*connector) (reset! *connector nil)) (defn restart [] (when @*connector (stop)) (start)) ``` -------------------------------- ### Test GET Request Body Source: https://pedestal.io/pedestal/0.8/guides/unit-testing.html Asserts that the response body of a GET request is 'Hello!'. The `:body` key of the response map is checked for equality. ```clojure (is (= "Hello!" (:body (response-for connector :get "/hello")))) ``` -------------------------------- ### Define GET /greet Route Handler Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Defines the handler for the GET /greet endpoint. It retrieves the :greeter component from the request and uses it to generate a message. ```clojure (ns app.routes (:require [app.components.greeter :as greeter])) (defn get-greeting [request] (let [greeter (get-in request [:components :greeter])] {:status 200 :body (greeter/generate-message! greeter)})) ``` -------------------------------- ### Test GET Request with Matcher Combinators Source: https://pedestal.io/pedestal/0.8/guides/unit-testing.html Uses the `matcher-combinators` library to assert the status, headers, and body of a GET request response in a single assertion. ```clojure (is (match? {:status 200 :headers {:content-type "text/plain"} :body "Hello!"} (response-for connector :get "/hello"))) ``` -------------------------------- ### Basic SSL Configuration for Pedestal Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-ssl.html Configure the connector to enable SSL, specify the SSL port, and provide the keystore path and password. This setup is for development or testing purposes; sensitive information like passwords should be managed securely in production. ```clojure (ns hello-ssl (:require [io.pedestal.connector :as conn] [io.pedestal.http.jetty :as jetty] [io.pedestal.log :as log])) (defn greet-handler [request] {:status 200 :body (format "Hello world from server %s using scheme %s!" (:server-name request) (:scheme request))}) __**(1)** (defn redirect-to-secure [secure-port] {:name :redirect-to-secure :enter (fn [{:keys [request route] :as context}] (if (-> request :scheme (= :http)) __**(2)** (let [{:keys [server-name uri query-string]} request redirect-url (format "https://%s:%s%s%s" server-name secure-port uri (if query-string (str "?" query-string) ""))] (log/info :in ::redirect-to-secure :route-name (:route-name route) :server-name server-name :redirect-url redirect-url) (assoc context :response {:status 302 :headers {"Location" redirect-url}})) __**(3)** context))}) (def routes #{["/:get [(redirect-to-secure 8443) greet-handler] :route-name :greet]}) (defn create-connector [] (-> (conn/default-connector-map 8080) __**(4)** (assoc :container-options {:ssl? true __**(5)** :ssl-port 8443 __**(6)** :keystore "./server.p12" __**(7)** :key-password "your-keystore-password-here" __**(8)** :sni-host-check? false __**(9)** :keystore-scal-interval 60}) __**(10)** (conn/with-default-interceptors) (conn/with-routes routes) (jetty/create-connector nil))) (defn start [] (conn/start! (create-connector))) ``` -------------------------------- ### Test GET Request Headers Source: https://pedestal.io/pedestal/0.8/guides/unit-testing.html Asserts that the 'content-type' header of a GET request response is 'text/plain'. It uses `get-in` to access nested map values. ```clojure (let [response (response-for connector :get "/hello")] (is (= "text/plain" (get-in response [:headers :content-type])))) ``` -------------------------------- ### Basic 'Hello World' Pedestal Application Source: https://pedestal.io/pedestal/0.8/guides/live-repl.html This code defines a basic Pedestal application with a single '/hello' route. The running connector is stored in an atom to survive namespace reloads. ```clojure (ns org.example.hello (:require [io.pedestal.connector :as conn] [io.pedestal.http.http-kit :as hk])) (defn hello-handler [_request] __**(1)** {:status 200 :body "Hello, World!"}) (def routes #{["/hello" :get hello-handler :route-name ::hello]}) __**(2)** (defn create-connector [] (-> (conn/default-connector-map 9999) (conn/with-default-interceptors) (conn/with-routes routes) __**(3)** (hk/create-connector nil))) (defonce *connector (atom nil)) __**(4)** (defn start [] (reset! *connector (conn/start! (create-connector)))) (defn stop [] (conn/stop! @*connector) (reset! *connector nil)) ``` -------------------------------- ### Define Get Greeting Interceptor Source: https://pedestal.io/pedestal/0.8/guides/pedestal-component-2.html Defines a Pedestal interceptor using `definterceptor` for handling GET requests. This interceptor depends on the greeter component to generate a message. ```clojure (ns app.components.handlers (:require [io.pedestal.interceptor :refer [definterceptor]] [app.components.greeter :as greeter])) (definterceptor get-greeting __**(1)** [greeter] __**(2)** (handle [_ _request] __**(3)** {:status 200 :body (greeter/generate-message! greeter)})) __**(4)** (defn new-get-greeting __**(5)** [] (map->get-greeting {})) ``` -------------------------------- ### Start Jaeger for Telemetry Source: https://pedestal.io/pedestal/0.8/guides/embedded-template.html This script downloads the Open Telemetry Java Agent, starts the Jaeger service in a Docker container, and opens the Jaeger UI in your browser. Execute `docker stop jaeger` to stop the container. ```bash $ ./start-jaeger.sh Downloading Open Telemetry Java Agent to target directory ... f7296a450ab2bfad684451ed7e0ed22125c0743f79e9675c4e15f593570986de Jaeger is running, execute `docker stop jaeger` to stop it. > ``` -------------------------------- ### Testing the '/hello' Route Source: https://pedestal.io/pedestal/0.8/guides/live-repl.html This command tests the '/hello' route of the running Pedestal application and displays the response. ```bash > http :9999/hello HTTP/1.1 200 OK Content-Security-Policy: object-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:; Content-Type: text/plain Date: Fri, 18 Nov 2022 23:41:49 GMT Strict-Transport-Security: max-age=31536000; includeSubdomains Transfer-Encoding: chunked X-Content-Type-Options: nosniff X-Download-Options: noopen X-Frame-Options: DENY X-Permitted-Cross-Domain-Policies: none X-XSS-Protection: 1; mode=block Hello, World! ``` -------------------------------- ### Get Accepted Type Source: https://pedestal.io/pedestal/0.8/guides/hello-world-content-types.html A helper function to retrieve the accepted content type from the request context. ```clojure (defn accepted-type [context] (get-in context [:request :accept :field] "text/plain")) ``` -------------------------------- ### Add File System Resource Routes Source: https://pedestal.io/pedestal/0.8/reference/resources.html Exposes files from a specified directory as resources under the default URI path '/'. Configure the :file-root option to point to the directory containing your static files. ```clojure (defn create-connector [] (-> (conn/default-connector-map 8890) (conn/with-default-interceptors) (conn/with-routes #{ ... } (resources/file-routes {:file-root "web/public"}))) ``` -------------------------------- ### Build and Run WAR Deployment Command Source: https://pedestal.io/pedestal/0.8/guides/war-deployment.html This command executes the Clojure script to build the WAR file. The first execution may take time to download dependencies. ```bash $ clojure -T:build war Copying cheshire-6.0.0.jar Copying transit-clj-1.0.333.jar Copying transit-java-1.0.371.jar Copying jackson-core-2.18.3.jar ... Copying ring-core-1.14.1.jar Copying tigris-0.1.2.jar Copying resources Copying src Copying web.xml Created target/app.war $ ``` -------------------------------- ### System Definition with Components Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Constructs the application system using `component/system-map`. It defines the 'greeter' component, a 'components' map to hold shared dependencies, and the 'pedestal' server, specifying their interdependencies. ```clojure (ns app.system (:require [com.stuartsierra.component :as component] [app.components.greeter :as greeter] app.pedestal)) (defn new-system [] (component/system-map :greeter (greeter/new-greeter) :components (component/using {} [:greeter]) :pedestal (component/using (app.pedestal/new-pedestal) [:components]))) ``` -------------------------------- ### Curl Request to Localhost Source: https://pedestal.io/pedestal/0.8/guides/hello-world.html Sends an HTTP GET request to the locally running Pedestal server on port 8890 to the '/greet' endpoint. ```bash $ curl -i http://127.0.0.1:8890/greet ``` -------------------------------- ### Testing the '/hello' Route with Response Body Only Source: https://pedestal.io/pedestal/0.8/guides/live-repl.html This command tests the '/hello' route and uses the '-pb' option to print only the response body, omitting headers. ```bash > http -pb :9999/hello __**(1)** Hello, World! ``` -------------------------------- ### Define Greeter Component Lifecycle Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Defines a Greeter component with a stateful atom for counting greetings. Implements the component/Lifecycle protocol for starting and stopping. ```clojure (ns app.components.greeter (:require [com.stuartsierra.component :as component] [clj-commons.humanize :as h])) (defrecord Greeter [*count] component/Lifecycle (start [this] (assoc this :*count (atom 0))) (stop [this] (assoc this :*count nil))) (defn new-greeter [] (map->Greeter {})) ``` -------------------------------- ### Route Definitions Source: https://pedestal.io/pedestal/0.8/guides/pedestal-with-component.html Defines the application routes, mapping HTTP methods and paths to handler functions. This example includes a single route for greeting. ```clojure (ns app.routes (:require [app.components.greeter :as greeter])) (defn get-greeting [request] (let [greeter (get-in request [:components :greeter])] {:status 200 :body (greeter/generate-message! greeter)})) (def routes #{["/api/greet" :get get-greeting :route-name :greet]}) ```