Skip to content

Commit 4ab5cb9

Browse files
Added webhook support for all relevant endpoints
1 parent c7abe2f commit 4ab5cb9

File tree

7 files changed

+507
-87
lines changed

7 files changed

+507
-87
lines changed

Cargo.lock

Lines changed: 33 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ blocking = ["reqwest/blocking"]
2626

2727
[dev-dependencies]
2828
wasm-bindgen-test = "0.3"
29+
tiny_http = "0.12.0"
30+
31+
2932

3033
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
3134
tokio = { version = "1", features = ["full"] }

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ async fn main() {
107107

108108
let options = WebOptions::default();
109109

110-
let pdf_bytes = client.pdf_from_markdown(html_template, markdown_files, options).await.unwrap();
110+
let pdf_bytes = client.pdf_from_markdown(html_template, markdown_files, options, None).await.unwrap();
111111
}
112112
```
113113

@@ -126,7 +126,7 @@ async fn main() {
126126
options.height = Some(1080);
127127
options.format = Some(ImageFormat::Png);
128128

129-
let image_bytes = client.screenshot_url("https://example.com", options).await.unwrap();
129+
let image_bytes = client.screenshot_url("https://example.com", options, None).await.unwrap();
130130

131131
println!("Screenshot captured: {} bytes", image_bytes.len());
132132
}
@@ -150,7 +150,7 @@ async fn main() {
150150
..Default::default()
151151
};
152152

153-
let pdf_bytes = client.pdf_from_doc(filename, file_content, options).await.unwrap();
153+
let pdf_bytes = client.pdf_from_doc(filename, file_content, options, None).await.unwrap();
154154
}
155155
```
156156

@@ -177,7 +177,7 @@ async fn main() {
177177
options.height = Some(600);
178178
options.format = Some(ImageFormat::Png);
179179

180-
let image_bytes = client.screenshot_html(html_content, options).await.unwrap();
180+
let image_bytes = client.screenshot_html(html_content, options, None).await.unwrap();
181181
}
182182
```
183183

@@ -197,7 +197,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
197197
let client = StreamingClient::new("http://localhost:3000");
198198

199199
let options = WebOptions::default();
200-
let mut stream = client.pdf_from_url("https://example.com", options).await?;
200+
let mut stream = client.pdf_from_url("https://example.com", options, None).await?;
201201

202202
// Create or overwrite the PDF file asynchronously
203203
let temp_dir = std::env::temp_dir();
@@ -232,7 +232,7 @@ fn main() {
232232
options.set_paper_format(PaperFormat::A4);
233233

234234
// Convert a URL to PDF
235-
let pdf_bytes = client.pdf_from_url("https://example.com", options).unwrap();
235+
let pdf_bytes = client.pdf_from_url("https://example.com", options, None).unwrap();
236236
}
237237
```
238238

src/client.rs

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ impl Client {
7878
pub fn new_with_client(base_url: &str, client: ReqwestClient) -> Self {
7979
// Strip trailing slashes
8080
let base_url = base_url.trim_end_matches('/');
81-
8281
Client {
8382
client,
8483
base_url: base_url.to_string(),
@@ -111,26 +110,37 @@ impl Client {
111110
}
112111

113112
/// Generic POST method that takes a multipart form and sends it.
113+
/// If webhook options are provided, their headers are added to the request.
114+
/// In the case of webhook usage, the server will respond with 204 No Content and no bytes,
115+
/// so we return empty bytes.
114116
async fn post(
115117
&self,
116118
endpoint: &str,
117119
form: multipart::Form,
118120
trace: Option<String>,
121+
webhook: Option<&WebhookOptions>,
119122
) -> Result<Bytes, Error> {
120123
let url = format!("{}/{}", self.base_url, endpoint);
121-
122124
let mut req = self.client.post(&url).multipart(form);
125+
123126
if let Some(trace) = trace {
124127
req = req.header("Gotenberg-Trace", trace);
125128
}
126-
129+
if let Some(webhook) = webhook {
130+
req = req.headers(webhook.to_headers());
131+
}
127132
// Add basic auth if username and password are provided
128133
if let (Some(username), Some(password)) = (&self.username, &self.password) {
129134
req = req.basic_auth(username, Some(password));
130135
}
131136

132137
let response: Response = req.send().await.map_err(Into::into)?;
133138

139+
// If webhook is enabled, the server returns 204 No Content.
140+
if response.status() == reqwest::StatusCode::NO_CONTENT {
141+
return Ok(Bytes::new());
142+
}
143+
134144
if !response.status().is_success() {
135145
let status = response.status();
136146
let body = response.text().await.unwrap_or_default();
@@ -144,17 +154,27 @@ impl Client {
144154
}
145155

146156
/// Convert a URL to a PDF using the Chromium engine.
147-
pub async fn pdf_from_url(&self, url: &str, options: WebOptions) -> Result<Bytes, Error> {
157+
pub async fn pdf_from_url(
158+
&self,
159+
url: &str,
160+
options: WebOptions,
161+
webhook: Option<&WebhookOptions>,
162+
) -> Result<Bytes, Error> {
148163
let trace = options.trace_id.clone();
149164
let form = multipart::Form::new().text("url", url.to_string());
150165
let form = options.fill_form(form);
151-
self.post("forms/chromium/convert/url", form, trace).await
166+
self.post("forms/chromium/convert/url", form, trace, webhook)
167+
.await
152168
}
153169

154170
/// Convert HTML to a PDF using the Chromium engine.
155-
pub async fn pdf_from_html(&self, html: &str, options: WebOptions) -> Result<Bytes, Error> {
171+
pub async fn pdf_from_html(
172+
&self,
173+
html: &str,
174+
options: WebOptions,
175+
webhook: Option<&WebhookOptions>,
176+
) -> Result<Bytes, Error> {
156177
let trace = options.trace_id.clone();
157-
158178
let form = multipart::Form::new();
159179
let file_bytes = html.to_string().into_bytes();
160180
let part = multipart::Part::bytes(file_bytes)
@@ -163,7 +183,8 @@ impl Client {
163183
.unwrap();
164184
let form = form.part("index.html", part);
165185
let form = options.fill_form(form);
166-
self.post("forms/chromium/convert/html", form, trace).await
186+
self.post("forms/chromium/convert/html", form, trace, webhook)
187+
.await
167188
}
168189

169190
/// Convert Markdown to a PDF using the Chromium engine.
@@ -189,6 +210,7 @@ impl Client {
189210
html_template: &str,
190211
markdown: HashMap<&str, &str>,
191212
options: WebOptions,
213+
webhook: Option<&WebhookOptions>,
192214
) -> Result<Bytes, Error> {
193215
let trace = options.trace_id.clone();
194216

@@ -220,7 +242,7 @@ impl Client {
220242
form
221243
};
222244

223-
self.post("forms/chromium/convert/markdown", form, trace)
245+
self.post("forms/chromium/convert/markdown", form, trace, webhook)
224246
.await
225247
}
226248

@@ -229,11 +251,12 @@ impl Client {
229251
&self,
230252
url: &str,
231253
options: ScreenshotOptions,
254+
webhook: Option<&WebhookOptions>,
232255
) -> Result<Bytes, Error> {
233256
let trace = options.trace_id.clone();
234257
let form = multipart::Form::new().text("url", url.to_string());
235258
let form = options.fill_form(form);
236-
self.post("forms/chromium/screenshot/url", form, trace)
259+
self.post("forms/chromium/screenshot/url", form, trace, webhook)
237260
.await
238261
}
239262

@@ -242,6 +265,7 @@ impl Client {
242265
&self,
243266
html: &str,
244267
options: ScreenshotOptions,
268+
webhook: Option<&WebhookOptions>,
245269
) -> Result<Bytes, Error> {
246270
let trace = options.trace_id.clone();
247271

@@ -253,7 +277,7 @@ impl Client {
253277
.unwrap();
254278
let form = form.part("index.html", part);
255279
let form = options.fill_form(form);
256-
self.post("forms/chromium/screenshot/html", form, trace)
280+
self.post("forms/chromium/screenshot/html", form, trace, webhook)
257281
.await
258282
}
259283

@@ -263,6 +287,7 @@ impl Client {
263287
html_template: &str,
264288
markdown: HashMap<&str, &str>,
265289
options: ScreenshotOptions,
290+
webhook: Option<&WebhookOptions>,
266291
) -> Result<Bytes, Error> {
267292
let trace = options.trace_id.clone();
268293

@@ -294,7 +319,7 @@ impl Client {
294319
form
295320
};
296321

297-
self.post("forms/chromium/screenshot/markdown", form, trace)
322+
self.post("forms/chromium/screenshot/markdown", form, trace, webhook)
298323
.await
299324
}
300325

@@ -318,14 +343,16 @@ impl Client {
318343
filename: &str,
319344
bytes: Vec<u8>,
320345
options: DocumentOptions,
346+
webhook: Option<&WebhookOptions>,
321347
) -> Result<Bytes, Error> {
322348
let trace = options.trace_id.clone();
323349

324350
let form = multipart::Form::new();
325351
let part = multipart::Part::bytes(bytes).file_name(filename.to_string());
326352
let form = form.part("files", part);
327353
let form = options.fill_form(form);
328-
self.post("forms/libreoffice/convert", form, trace).await
354+
self.post("forms/libreoffice/convert", form, trace, webhook)
355+
.await
329356
}
330357

331358
/// Transforms a PDF file into the requested PDF/A format and/or PDF/UA.
@@ -334,6 +361,7 @@ impl Client {
334361
pdf_bytes: Vec<u8>,
335362
pdfa: Option<PDFFormat>,
336363
pdfua: bool,
364+
webhook: Option<&WebhookOptions>,
337365
) -> Result<Bytes, Error> {
338366
let form = multipart::Form::new();
339367
let part = multipart::Part::bytes(pdf_bytes).file_name("file.pdf".to_string());
@@ -342,7 +370,8 @@ impl Client {
342370
form = form.text("pdfa", pdfa.to_string());
343371
}
344372
let form = form.text("pdfua", pdfua.to_string());
345-
self.post("forms/pdfengines/convert", form, None).await
373+
self.post("forms/pdfengines/convert", form, None, webhook)
374+
.await
346375
}
347376

348377
/// Read the metadata of a PDF file
@@ -361,7 +390,7 @@ impl Client {
361390
}
362391

363392
let bytes = self
364-
.post("forms/pdfengines/metadata/read", form, None)
393+
.post("forms/pdfengines/metadata/read", form, None, None)
365394
.await?;
366395
let metadata: MeatadataContainer = serde_json::from_slice(&bytes).map_err(|e| {
367396
Error::ParseError(
@@ -379,6 +408,7 @@ impl Client {
379408
&self,
380409
pdf_bytes: Vec<u8>,
381410
metadata: HashMap<String, serde_json::Value>,
411+
webhook: Option<&WebhookOptions>,
382412
) -> Result<Bytes, Error> {
383413
let form = multipart::Form::new();
384414
let part = multipart::Part::bytes(pdf_bytes).file_name("file.pdf".to_string());
@@ -388,7 +418,7 @@ impl Client {
388418
})?;
389419
let part = multipart::Part::text(metadata);
390420
let form = form.part("metadata", part);
391-
self.post("forms/pdfengines/metadata/write", form, None)
421+
self.post("forms/pdfengines/metadata/write", form, None, webhook)
392422
.await
393423
}
394424

0 commit comments

Comments
 (0)