0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

🎉 Add basic error handling to exporter app.

This commit is contained in:
Andrey Antukh 2020-06-30 20:32:11 +02:00 committed by Hirunatan
parent 20c4b46930
commit a1f0625bec
7 changed files with 107 additions and 26 deletions

View file

@ -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

View file

@ -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++) {

View file

@ -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

View file

@ -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"

View file

@ -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

View 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)))

View file

@ -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)))))]