Skip to content

Commit

Permalink
emhanced :multipart module
Browse files Browse the repository at this point in the history
  • Loading branch information
jlangch committed Apr 1, 2024
1 parent 6a2a215 commit 5057a18
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ public DocSection section() {
bb_create.addItem(diBuilder.getDocItem("bytebuf"));
bb_create.addItem(diBuilder.getDocItem("bytebuf-allocate"));
bb_create.addItem(diBuilder.getDocItem("bytebuf-allocate-random"));
bb_create.addItem(diBuilder.getDocItem("bytebuf-from-string"));
bb_create.addItem(diBuilder.getDocItem("bytebuf-byte-order!"));
bb_create.addItem(diBuilder.getDocItem("bytebuf-byte-order"));

final DocSection string = new DocSection("String", "bytebuf.string");
all.addSection(string);
string.addItem(diBuilder.getDocItem("bytebuf-from-string"));
string.addItem(diBuilder.getDocItem("bytebuf-to-string"));

final DocSection bb_test = new DocSection("Test", "bytebuf.test");
all.addSection(bb_test);
bb_test.addItem(diBuilder.getDocItem("empty?"));
Expand All @@ -59,7 +63,6 @@ public DocSection section() {
bb_use.addItem(diBuilder.getDocItem("count"));
bb_use.addItem(diBuilder.getDocItem("bytebuf-capacity"));
bb_use.addItem(diBuilder.getDocItem("bytebuf-limit"));
bb_use.addItem(diBuilder.getDocItem("bytebuf-to-string"));
bb_use.addItem(diBuilder.getDocItem("bytebuf-to-list"));
bb_use.addItem(diBuilder.getDocItem("bytebuf-sub"));
bb_use.addItem(diBuilder.getDocItem("bytebuf-pos"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ public DocSection section() {
hex.addItem(diBuilder.getDocItem("str/bytebuf-to-hex"));
hex.addItem(diBuilder.getDocItem("str/format-bytebuf"));

final DocSection bytebuf = new DocSection("Bytebuf", "primitives.strings.bytebuf");
strings.addSection(bytebuf);
bytebuf.addItem(diBuilder.getDocItem("bytebuf-from-string"));
bytebuf.addItem(diBuilder.getDocItem("bytebuf-to-string"));

final DocSection encode = new DocSection("Encode/Decode", "primitives.strings.encode");
strings.addSection(encode);
encode.addItem(diBuilder.getDocItem("str/encode-base64"));
Expand Down
146 changes: 104 additions & 42 deletions src/main/resources/com/github/jlangch/venice/multipart.venice
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
(import :java.nio.file.Paths)


(defonce ^:private boundary-value (str (rand-bigint 256)))
(defonce ^:private boundary-value (str (rand-bigint 128)))

(defonce ^:private dash "--")
(defonce ^:private dq "\"")
Expand All @@ -44,64 +44,126 @@
(defonce ^:private content-type "Content-Type: ")


(defn to-bytebuf [data]
(defn
^{ :arglists '(
"(render parts)" )
:doc
"""
Renders a map of named parts as *multipart* binary data.

The part name must be a string and the part data may be of type:
* string
* string ("file:/user/foo/image.png" to reference a file)
* map (describing a part as :name, :mimetype, and :data)
* io/file
* all other part data types are converted with `(str data)` to a string

Returns a bytebuf.
"""
:examples '(
"""
(do
(load-module :multipart ['multipart :as 'm])

(->> (m/render { "Part-1" "xxxxxxxxxxx"
"Part-2" "yyyyyyyyyyy"})
(bytebuf-to-string)
(println)))
""",
"""
(do
(load-module :multipart ['multipart :as 'm])

(m/render { "Part-1" "xxxxxxxxxxx"
"Part-2" "file:/user/foo/image.png"
"Part-3" (io/file "/user/foo/image.png")
"Part-4" {:name "data.xml"
:mimetype "application/xml"
:data (bytebuf-from-string
"<user><name>foo</name></user>"
:utf-8)}})
""" ) }

render [data]

(assert (map? data))
(assert (not (empty? data)))

(try-with [os (io/bytebuf-out-stream)]
(doseq [[name value] data]
(if (file-protocol? v)
(io/spit-stream os (to-bytebuf-file name value))
(io/spit-stream os (to-bytebuf-simple name value)))
@os)))

(doseq [[name value] data] (render-part name value os))
@os))

(defn- to-bytebuf-file [name value]

(defn- render-part [name value os]
(try
(assert (string? name))

(cond
(file-url? value) (->as (. :URL :new value) f
(. f :getPath)
(. :File :new f)
(render-file-part name f os))

(io/file? value) (render-file-part name value os)

(map? value) (render-file-data-part name
(:name part)
(:mimetype part)
(:data part)
os)
(string? value) (render-string-part name value os)

:else (render-string-part name (str value) os))
(catch :Exception e
(throw (ex :VncException (str "Failed to process multipart item " name)
e)))))


(defn- render-file-part [name file os]
(assert (string? name))
(assert (io/file? file))

(try-with [os (io/bytebuf-out-stream)]
(let [v-file (->as (. :URL :new value) f
(. f :getPath)
(. :File :new f))
v-file-name (io/file-path v-file)
v-mime-type (mimetypes/mimetypes/probe-content-type v-file)]
(when (nil? v-mime-type)
(try
(let [v-file-name (io/file-path file)
v-file-mimetype (mimetypes/probe-content-type file)
v-file-data (. :Files :readAllBytes (. file :toPath))]
(when (nil? v-file-mimetype)
(throw (ex :VncException (str "Failed to get mimetype for file " v-file-name))))

(io/spit-stream os (str-to-bytebuf (str dash boundary-value nl)))
(io/spit-stream os (str-to-bytebuf disposition))

(io/spit-stream os (str-to-bytebuf (str field-name dq name dq file-name dq v-file-name dq nl)))
(io/spit-stream os (str-to-bytebuf (str content-type v-mime-type nl)))
(io/spit-stream os (str-to-bytebuf nl))
(io/spit-stream os (. :Files :readAllBytes (. v-file :toPath)))
(io/spit-stream os (str-to-bytebuf nl))

(io/spit-stream os (str-to-bytebuf (str dash boundary-value dash nl)))
@os)
(render-file-data-part name v-file-name v-file-mimetype v-file-data os))
(catch :Exception e
(throw (ex :VncException (str "Failed do process file " v-file-name) e)))))


(defn- to-bytebuf-simple [name value]
(assert (string? name))

(try-with [os (io/bytebuf-out-stream)]
(io/spit-stream os (str-to-bytebuf (str dash boundary-value nl)))
(io/spit-stream os (str-to-bytebuf disposition))
(defn- render-file-data-part [name v-file-name v-file-mimetype v-file-data os]
(assert (string? v-file-name))
(assert (string? v-file-mimetype))
(assert (bytebuf? v-file-data))

(io/spit-stream os (str-to-bytebuf (str field-name dq name dq nl)))
(io/spit-stream os (str-to-bytebuf nl))
((io/spit-stream os str-to-bytebuf (str value nl)) )
(io/spit-stream os (bytebuf-from-string (str dash boundary-value nl)))
(io/spit-stream os (bytebuf-from-string disposition))

((io/spit-stream os str-to-bytebuf (str dash boundary-value dash nl)))

@os))
(io/spit-stream os (bytebuf-from-string (str field-name dq name dq file-name dq v-file-name dq nl)))
(io/spit-stream os (bytebuf-from-string (str content-type v-file-mimetype nl)))
(io/spit-stream os (bytebuf-from-string nl))
(io/spit-stream os v-file-data)
(io/spit-stream os (bytebuf-from-string nl))

(io/spit-stream os (bytebuf-from-string (str dash boundary-value dash nl))))


(defn- render-string-part [name text os]
(assert (string? name))

(io/spit-stream os (bytebuf-from-string (str dash boundary-value nl)))
(io/spit-stream os (bytebuf-from-string disposition))

(io/spit-stream os (bytebuf-from-string (str field-name dq name dq nl)))
(io/spit-stream os (bytebuf-from-string nl))
(io/spit-stream os (bytebuf-from-string (str text nl)))

(defn- str-to-bytebuf [s]
(bytebuf-from-string s :UTF-8))
(io/spit-stream os (bytebuf-from-string (str dash boundary-value dash nl))))


(defn- file-protocol? [v]
(defn- file-url? [v]
(and (string? v) (str/starts-with? v "file:")))

0 comments on commit 5057a18

Please sign in to comment.