mirror of
https://github.com/penpot/penpot.git
synced 2025-03-11 23:31:21 -05:00
🎉 Add basic error handling to exporter app.
This commit is contained in:
parent
20c4b46930
commit
a1f0625bec
7 changed files with 107 additions and 26 deletions
|
@ -9,7 +9,6 @@
|
|||
(:refer-clojure :exclude [assert])
|
||||
#?(:cljs (:require-macros [uxbox.common.spec :refer [assert]]))
|
||||
(:require
|
||||
#?(:clj [datoteka.core :as fs])
|
||||
#?(:clj [clojure.spec.alpha :as s]
|
||||
:cljs [cljs.spec.alpha :as s])
|
||||
[expound.alpha :as expound]
|
||||
|
@ -85,15 +84,6 @@
|
|||
v
|
||||
::s/invalid))
|
||||
|
||||
#?(:clj
|
||||
(defn path-conformer
|
||||
[v]
|
||||
(cond
|
||||
(string? v) (fs/path v)
|
||||
(fs/path? v) v
|
||||
:else ::s/invalid)))
|
||||
|
||||
|
||||
;; --- Default Specs
|
||||
|
||||
(s/def ::inst inst?)
|
||||
|
@ -107,7 +97,6 @@
|
|||
(s/def ::not-empty-string (s/and string? #(not (str/empty? %))))
|
||||
(s/def ::url string?)
|
||||
(s/def ::fn fn?)
|
||||
#?(:clj (s/def ::path (s/conformer path-conformer str)))
|
||||
|
||||
;; --- Macros
|
||||
|
||||
|
|
|
@ -20,8 +20,13 @@ function fill(buf) {
|
|||
return buf;
|
||||
};
|
||||
|
||||
// NOTE: NodeJS compatibility
|
||||
if (typeof require === "function") {
|
||||
global.crypto = require("crypto");
|
||||
}
|
||||
|
||||
if (global.crypto === undefined) {
|
||||
console.warn("No high quality RNG available, switching back to Math.random.", platform);
|
||||
console.warn("No high quality RNG available, switching back to Math.random.");
|
||||
|
||||
fill = function(buf) {
|
||||
for (let i = 0, r; i < buf.length; i++) {
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
{:dependencies
|
||||
[[funcool/promesa "5.1.0"]
|
||||
[danlentz/clj-uuid "0.1.9"]
|
||||
[funcool/cuerdas "2020.03.26-3"]
|
||||
[lambdaisland/glogi "1.0.63"]
|
||||
[metosin/reitit-core "0.5.2"]]
|
||||
:source-paths ["src"]
|
||||
[metosin/reitit-core "0.5.2"]
|
||||
[com.cognitect/transit-cljs "0.8.264"]]
|
||||
|
||||
:source-paths ["src" "../common"]
|
||||
:nrepl {:port 3497}
|
||||
|
||||
:builds
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
[lambdaisland.glogi :as log]
|
||||
[app.browser :as bwr]
|
||||
[app.http.screenshot :refer [bitmap-handler]]
|
||||
[app.util.transit :as t]
|
||||
[reitit.core :as r]
|
||||
[cuerdas.core :as str]
|
||||
["koa" :as koa]
|
||||
["http" :as http])
|
||||
(:import
|
||||
|
@ -29,6 +31,31 @@
|
|||
:params params
|
||||
:query-params qparams)))))
|
||||
|
||||
(defn- handle-error
|
||||
[error request]
|
||||
(let [{:keys [type message code] :as data} (ex-data error)]
|
||||
(cond
|
||||
(= :validation type)
|
||||
(let [header (get-in request [:headers "accept"])]
|
||||
(if (and (str/starts-with? header "text/html")
|
||||
(= :spec-validation (:code data)))
|
||||
{:status 400
|
||||
:headers {"content-type" "text/html"}
|
||||
:body (str "<pre style='font-size:16px'>" (:explain data) "</pre>\n")}
|
||||
{:status 400
|
||||
:headers {"x-metadata" (t/encode data)}
|
||||
:body ""}))
|
||||
|
||||
:else
|
||||
(do
|
||||
(log/error :msg "Unexpected error"
|
||||
:error error)
|
||||
{:status 500
|
||||
:headers {"x-metadata" (t/encode {:type :unexpected
|
||||
:message (ex-message error)})}
|
||||
:body ""}))))
|
||||
|
||||
|
||||
(defn- handle-response
|
||||
[ctx {:keys [body headers status] :or {headers {} status 200}}]
|
||||
(run! (fn [[k v]] (.set ^js ctx k v)) headers)
|
||||
|
@ -36,15 +63,30 @@
|
|||
(set! (.-status ^js ctx) status)
|
||||
nil)
|
||||
|
||||
(defn- parse-headers
|
||||
[ctx]
|
||||
(let [orig (unchecked-get ctx "headers")]
|
||||
(persistent!
|
||||
(reduce #(assoc! %1 %2 (unchecked-get orig %2))
|
||||
(transient {})
|
||||
(js/Object.keys orig)))))
|
||||
|
||||
(defn- wrap-handler
|
||||
[f extra]
|
||||
(fn [ctx]
|
||||
(let [cookies (unchecked-get ctx "cookies")
|
||||
request (assoc extra :ctx ctx :cookies cookies)]
|
||||
headers (parse-headers ctx)
|
||||
request (assoc extra
|
||||
:ctx ctx
|
||||
:headers headers
|
||||
:cookies cookies)]
|
||||
(-> (p/do! (f request))
|
||||
(p/then (fn [rsp]
|
||||
(when (map? rsp)
|
||||
(handle-response ctx rsp))))))))
|
||||
(p/then (fn [rsp]
|
||||
(when (map? rsp)
|
||||
(handle-response ctx rsp))))
|
||||
(p/catch (fn [err]
|
||||
(->> (handle-error err request)
|
||||
(handle-response ctx))))))))
|
||||
|
||||
(def routes
|
||||
[["/export"
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
(:require
|
||||
[app.browser :as bwr]
|
||||
[app.config :as cfg]
|
||||
[promesa.core :as p]))
|
||||
[cljs.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[uxbox.common.exceptions :as exc :include-macros true]
|
||||
[uxbox.common.spec :as us]))
|
||||
|
||||
(defn- load-and-screenshot
|
||||
[page url cookie]
|
||||
|
@ -27,13 +30,17 @@
|
|||
(load-and-screenshot page url cookie)))]
|
||||
(bwr/exec! browser on-browser)))
|
||||
|
||||
(s/def ::page-id ::us/uuid)
|
||||
(s/def ::object-id ::us/uuid)
|
||||
(s/def ::bitmap-handler-params
|
||||
(s/keys :req-un [::page-id ::object-id]))
|
||||
|
||||
(defn bitmap-handler
|
||||
[{:keys [params browser cookies] :as request}]
|
||||
(let [page-id (get-in params [:query :page-id])
|
||||
object-id (get-in params [:query :object-id])
|
||||
token (.get ^js cookies "auth-token")]
|
||||
(-> (take-screenshot browser {:page-id page-id
|
||||
:object-id object-id
|
||||
(let [params (us/conform ::bitmap-handler-params (:query params))
|
||||
token (.get ^js cookies "auth-token")]
|
||||
(-> (take-screenshot browser {:page-id (:page-id params)
|
||||
:object-id (:object-id params)
|
||||
:token token})
|
||||
(p/then (fn [result]
|
||||
{:status 200
|
||||
|
|
32
exporter/src/app/util/transit.cljs
Normal file
32
exporter/src/app/util/transit.cljs
Normal file
|
@ -0,0 +1,32 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns app.util.transit
|
||||
(:require
|
||||
[cognitect.transit :as t]))
|
||||
|
||||
;; --- Transit Handlers
|
||||
|
||||
(def ^:private +read-handlers+
|
||||
{"u" uuid})
|
||||
|
||||
(def ^:private +write-handlers+
|
||||
{})
|
||||
|
||||
;; --- Public Api
|
||||
|
||||
(defn decode
|
||||
[data]
|
||||
(let [r (t/reader :json {:handlers +read-handlers+})]
|
||||
(t/read r data)))
|
||||
|
||||
(defn encode
|
||||
[data]
|
||||
(let [w (t/writer :json {:handlers +write-handlers+})]
|
||||
(t/write w data)))
|
|
@ -14,6 +14,7 @@
|
|||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.main.data.messages :as dm]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -67,8 +68,10 @@
|
|||
(swap! loading? not)
|
||||
(->> (request-screenshot (:id page) (:id shape))
|
||||
(rx/subs
|
||||
(fn [{:keys [status body]}]
|
||||
(trigger-download (:name shape) body))
|
||||
(fn [{:keys [status body] :as response}]
|
||||
(if (= status 200)
|
||||
(trigger-download (:name shape) body)
|
||||
(st/emit! (dm/error (tr "errors.unexpected-error")))))
|
||||
(constantly nil)
|
||||
(fn []
|
||||
(swap! loading? not)))))]
|
||||
|
|
Loading…
Add table
Reference in a new issue