mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-15 11:52:14 +01:00
Merge pull request #153 from thecodingmachine/custom_headers
Custom headers
This commit is contained in:
@@ -18,7 +18,7 @@ Unless your project already has a PSR7 `HttpClient`, install `php-http/guzzle6-a
|
||||
$ composer require php-http/guzzle6-adapter
|
||||
```
|
||||
|
||||
Then the PHP client:
|
||||
Then the [PHP client](https://github.com/thecodingmachine/gotenberg-php-client):
|
||||
|
||||
```bash
|
||||
$ composer require thecodingmachine/gotenberg-php-client
|
||||
|
||||
@@ -59,7 +59,7 @@ use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -146,7 +146,7 @@ $footer = DocumentFactory::makeFromPath('footer.html', 'footer.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setHeader($header);
|
||||
$request->setFooter($footer);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -237,7 +237,7 @@ $assets = [
|
||||
];
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setAssets($assets);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -296,7 +296,7 @@ $request = new HTMLRequest($index);
|
||||
$request->setPaperSize(Request::A4);
|
||||
$request->setMargins(Request::NO_MARGINS);
|
||||
$request->setLandscape(true);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -345,7 +345,7 @@ $client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setWaitDelay(5.5);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -397,6 +397,6 @@ $client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setGoogleChromeRpccBufferSize(1048576);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -51,6 +51,57 @@ use TheCodingMachine\Gotenberg\URLRequest;
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$request = new URLRequest('https://google.com');
|
||||
$request->setMargins(Request::NO_MARGINS);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
## Custom HTTP headers
|
||||
|
||||
You may send your own HTTP headers to the `remoteURL`.
|
||||
|
||||
For instance, by adding the HTTP header `Gotenberg-Remoteurl-Your-Header` to your request,
|
||||
the API will send a request to the `remoteURL` with the HTTP header `Your-Header`.
|
||||
|
||||
> **Attention:** the API uses a canonical format for the HTTP headers:
|
||||
> it transforms the first
|
||||
> letter and any letter following a hyphen to upper case;
|
||||
> the rest are converted to lowercase. For example, the
|
||||
> canonical key for `accept-encoding` is `Accept-Encoding`.
|
||||
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/url \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--header 'Gotenberg-Remoteurl-Your-Header: Foo' \
|
||||
--form remoteURL=https://google.com \
|
||||
-o result.pdf
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```golang
|
||||
import "github.com/thecodingmachine/gotenberg-go-client/v6"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := gotenberg.NewURLRequest("https://google.com")
|
||||
req.AddRemoteURLHTTPHeader("Your-Header", "Foo")
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
```
|
||||
|
||||
### PHP
|
||||
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\URLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$request = new URLRequest('https://google.com');
|
||||
$request->addRemoteURLHTTPHeader('Your-Header', 'Foo')
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -65,6 +65,6 @@ $markdowns = [
|
||||
DocumentFactory::makeFromPath('file.md', 'file.md'),
|
||||
];
|
||||
$request = new MarkdownRequest($index, $markdowns);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -64,7 +64,7 @@ $files = [
|
||||
DocumentFactory::makeFromPath('document2.docx', 'document2.docx'),
|
||||
];
|
||||
$request = new OfficeRequest($files);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -112,6 +112,6 @@ $files = [
|
||||
];
|
||||
$request = new OfficeRequest($files);
|
||||
$request->setLandscape(true);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -50,6 +50,6 @@ $files = [
|
||||
DocumentFactory::makeFromPath('file2.pdf', 'file2.pdf'),
|
||||
];
|
||||
$request = new MergeRequest($files);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -48,6 +48,6 @@ $client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client()
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setWaitTimeout(2.5);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
```
|
||||
|
||||
@@ -58,9 +58,7 @@ It takes a float as value (e.g `2.5` for 2.5 seconds).
|
||||
|
||||
> You may also define this value globally: see the [environment variables](#environment_variables.default_webhook_url_timeout) section.
|
||||
|
||||
### Examples
|
||||
|
||||
#### cURL
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
@@ -71,7 +69,7 @@ $ curl --request POST \
|
||||
--form webhookURLTimeout=2.5
|
||||
```
|
||||
|
||||
#### Go
|
||||
### Go
|
||||
|
||||
```golang
|
||||
import "github.com/thecodingmachine/gotenberg-go-client/v6"
|
||||
@@ -85,7 +83,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
#### PHP
|
||||
### PHP
|
||||
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
@@ -99,3 +97,56 @@ $request->setWebhookURL('http://myapp.com/webhook/');
|
||||
$request->setWebhookURLTimeout(2.5);
|
||||
$resp = $client->post($request);
|
||||
```
|
||||
|
||||
## Custom HTTP headers
|
||||
|
||||
You may send your own HTTP headers to the `webhookURL`.
|
||||
|
||||
For instance, by adding the HTTP header `Gotenberg-Webhookurl-Your-Header` to your request,
|
||||
the API will send a request to the `webhookURL` with the HTTP header `Your-Header`.
|
||||
|
||||
> **Attention:** the API uses a canonical format for the HTTP headers:
|
||||
> it transforms the first
|
||||
> letter and any letter following a hyphen to upper case;
|
||||
> the rest are converted to lowercase. For example, the
|
||||
> canonical key for `accept-encoding` is `Accept-Encoding`.
|
||||
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/html \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--header 'Gotenberg-Webhookurl-Your-Header: Foo' \
|
||||
--form files=@index.html \
|
||||
--form webhookURL='http://myapp.com/webhook/'
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```golang
|
||||
import "github.com/thecodingmachine/gotenberg-go-client/v6"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req, _ := gotenberg.NewHTMLRequest("index.html")
|
||||
req.WebhookURL("http://myapp.com/webhook/")
|
||||
req.AddWebhookURLHTTPHeader("Your-Header", "Foo")
|
||||
resp, _ := c.Post(req)
|
||||
}
|
||||
```
|
||||
|
||||
### PHP
|
||||
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setWebhookURL('http://myapp.com/webhook/');
|
||||
$request->addWebhookURLHTTPHeader('Your-Header', 'Foo');
|
||||
$resp = $client->post($request);
|
||||
```
|
||||
160
docs/index.html
160
docs/index.html
@@ -233,7 +233,7 @@ Gotenberg API is available at <a href="http://localhost:3000">http://localhost:3
|
||||
<pre class="chroma">$ composer require php-http/guzzle6-adapter
|
||||
</pre>
|
||||
|
||||
<p>Then the PHP client:</p>
|
||||
<p>Then the <a href="https://github.com/thecodingmachine/gotenberg-php-client">PHP client</a>:</p>
|
||||
|
||||
<pre class="chroma">$ composer require thecodingmachine/gotenberg-php-client
|
||||
</pre>
|
||||
@@ -474,7 +474,7 @@ use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -569,7 +569,7 @@ $footer = DocumentFactory::makeFromPath('footer.html', 'footer.html&
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setHeader($header);
|
||||
$request->setFooter($footer);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -665,7 +665,7 @@ $assets = [
|
||||
];
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setAssets($assets);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -731,7 +731,7 @@ $request = new HTMLRequest($index);
|
||||
$request->setPaperSize(Request::A4);
|
||||
$request->setMargins(Request::NO_MARGINS);
|
||||
$request->setLandscape(true);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -787,7 +787,7 @@ $client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setWaitDelay(5.5);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -846,7 +846,7 @@ $client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setGoogleChromeRpccBufferSize(1048576);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -912,7 +912,65 @@ use TheCodingMachine\Gotenberg\URLRequest;
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$request = new URLRequest('https://google.com');
|
||||
$request->setMargins(Request::NO_MARGINS);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="url.custom_http_headers" href="#url.custom_http_headers">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Custom HTTP headers</h2>
|
||||
|
||||
<p>You may send your own HTTP headers to the <code>remoteURL</code>.</p>
|
||||
|
||||
<p>For instance, by adding the HTTP header <code>Gotenberg-Remoteurl-Your-Header</code> to your request,
|
||||
the API will send a request to the <code>remoteURL</code> with the HTTP header <code>Your-Header</code>.</p>
|
||||
|
||||
<blockquote>
|
||||
<p><strong>Attention:</strong> the API uses a canonical format for the HTTP headers:
|
||||
it transforms the first
|
||||
letter and any letter following a hyphen to upper case;
|
||||
the rest are converted to lowercase. For example, the
|
||||
canonical key for <code>accept-encoding</code> is <code>Accept-Encoding</code>.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="url.custom_http_headers.c_url" href="#url.custom_http_headers.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/url <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Gotenberg-Remoteurl-Your-Header: Foo'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">remoteURL</span><span class="o">=</span>https://google.com <span class="se">\
|
||||
</span><span class="se"></span> -o result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="url.custom_http_headers.go" href="#url.custom_http_headers.go">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Go</h3>
|
||||
|
||||
<pre class="chroma"><span class="kn">import</span> <span class="s">"github.com/thecodingmachine/gotenberg-go-client/v6"</span>
|
||||
|
||||
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nf">NewURLRequest</span><span class="p">(</span><span class="s">"https://google.com"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nf">AddRemoteURLHTTPHeader</span><span class="p">(</span><span class="s">"Your-Header"</span><span class="p">,</span> <span class="s">"Foo"</span><span class="p">)</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nf">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="url.custom_http_headers.php" href="#url.custom_http_headers.php">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<pre class="chroma">use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\URLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$request = new URLRequest('https://google.com');
|
||||
$request->addRemoteURLHTTPHeader('Your-Header', 'Foo')
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -989,7 +1047,7 @@ $markdowns = [
|
||||
DocumentFactory::makeFromPath('file.md', 'file.md'),
|
||||
];
|
||||
$request = new MarkdownRequest($index, $markdowns);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -1070,7 +1128,7 @@ $files = [
|
||||
DocumentFactory::makeFromPath('document2.docx', 'document2.docx'),
|
||||
];
|
||||
$request = new OfficeRequest($files);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -1123,7 +1181,7 @@ $files = [
|
||||
];
|
||||
$request = new OfficeRequest($files);
|
||||
$request->setLandscape(true);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -1188,7 +1246,7 @@ $files = [
|
||||
DocumentFactory::makeFromPath('file2.pdf', 'file2.pdf'),
|
||||
];
|
||||
$request = new MergeRequest($files);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -1251,7 +1309,7 @@ $client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setWaitTimeout(2.5);
|
||||
$dest = "result.pdf";
|
||||
$dest = 'result.pdf';
|
||||
$client->store($request, $dest);
|
||||
</pre>
|
||||
|
||||
@@ -1326,13 +1384,9 @@ $resp = $client->post($request);
|
||||
<p>You may also define this value globally: see the <a href="#environment_variables.default_webhook_url_timeout">environment variables</a> section.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.timeout.examples" href="#webhook.timeout.examples">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.timeout.c_url" href="#webhook.timeout.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Examples</h3>
|
||||
|
||||
<h4 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.timeout.examples.c_url" href="#webhook.timeout.examples.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>cURL</h4>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/html <span class="se">\
|
||||
@@ -1342,9 +1396,9 @@ $resp = $client->post($request);
|
||||
</span><span class="se"></span> --form <span class="nv">webhookURLTimeout</span><span class="o">=</span>2.5
|
||||
</pre>
|
||||
|
||||
<h4 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.timeout.examples.go" href="#webhook.timeout.examples.go">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.timeout.go" href="#webhook.timeout.go">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Go</h4>
|
||||
</a>Go</h3>
|
||||
|
||||
<pre class="chroma"><span class="kn">import</span> <span class="s">"github.com/thecodingmachine/gotenberg-go-client/v6"</span>
|
||||
|
||||
@@ -1357,9 +1411,9 @@ $resp = $client->post($request);
|
||||
<span class="p">}</span>
|
||||
</pre>
|
||||
|
||||
<h4 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.timeout.examples.php" href="#webhook.timeout.examples.php">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.timeout.php" href="#webhook.timeout.php">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h4>
|
||||
</a>PHP</h3>
|
||||
|
||||
<pre class="chroma">use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
@@ -1371,6 +1425,66 @@ $request = new HTMLRequest($index);
|
||||
$request->setWebhookURL('http://myapp.com/webhook/');
|
||||
$request->setWebhookURLTimeout(2.5);
|
||||
$resp = $client->post($request);
|
||||
</pre>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.custom_http_headers" href="#webhook.custom_http_headers">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Custom HTTP headers</h2>
|
||||
|
||||
<p>You may send your own HTTP headers to the <code>webhookURL</code>.</p>
|
||||
|
||||
<p>For instance, by adding the HTTP header <code>Gotenberg-Webhookurl-Your-Header</code> to your request,
|
||||
the API will send a request to the <code>webhookURL</code> with the HTTP header <code>Your-Header</code>.</p>
|
||||
|
||||
<blockquote>
|
||||
<p><strong>Attention:</strong> the API uses a canonical format for the HTTP headers:
|
||||
it transforms the first
|
||||
letter and any letter following a hyphen to upper case;
|
||||
the rest are converted to lowercase. For example, the
|
||||
canonical key for <code>accept-encoding</code> is <code>Accept-Encoding</code>.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.custom_http_headers.c_url" href="#webhook.custom_http_headers.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/html <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Gotenberg-Webhookurl-Your-Header: Foo'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">webhookURL</span><span class="o">=</span><span class="s1">'http://myapp.com/webhook/'</span>
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.custom_http_headers.go" href="#webhook.custom_http_headers.go">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Go</h3>
|
||||
|
||||
<pre class="chroma"><span class="kn">import</span> <span class="s">"github.com/thecodingmachine/gotenberg-go-client/v6"</span>
|
||||
|
||||
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nf">NewHTMLRequest</span><span class="p">(</span><span class="s">"index.html"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nf">WebhookURL</span><span class="p">(</span><span class="s">"http://myapp.com/webhook/"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nf">AddWebhookURLHTTPHeader</span><span class="p">(</span><span class="s">"Your-Header"</span><span class="p">,</span> <span class="s">"Foo"</span><span class="p">)</span>
|
||||
<span class="nx">resp</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">c</span><span class="p">.</span><span class="nf">Post</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.custom_http_headers.php" href="#webhook.custom_http_headers.php">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<pre class="chroma">use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setWebhookURL('http://myapp.com/webhook/');
|
||||
$request->addWebhookURLHTTPHeader('Your-Header', 'Foo');
|
||||
$resp = $client->post($request);
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -138,6 +138,7 @@ func urlHandler(c echo.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts.CustomHTTPHeaders = resource.RemoteURLCustomHTTPHeaders(r)
|
||||
if !r.HasArg(resource.RemoteURLArgKey) {
|
||||
return xerror.Invalid(
|
||||
op,
|
||||
@@ -322,20 +323,50 @@ func convertAsync(ctx context.Context, p printer.Printer, filename, fpath string
|
||||
defer f.Close() // nolint: errcheck
|
||||
logger.DebugfOp(
|
||||
op,
|
||||
"sending result file '%s' to '%s'",
|
||||
"preparing to send result file '%s' to '%s'...",
|
||||
filename,
|
||||
webhookURL,
|
||||
)
|
||||
httpClient := &http.Client{
|
||||
Timeout: xtime.Duration(webhookURLTimeout),
|
||||
}
|
||||
resp, err := httpClient.Post(webhookURL, "application/pdf", f) /* #nosec */
|
||||
req, err := http.NewRequest(http.MethodPost, webhookURL, f)
|
||||
if err != nil {
|
||||
xerr := xerror.New(op, err)
|
||||
logger.ErrorOp(xerror.Op(xerr), xerr)
|
||||
return
|
||||
}
|
||||
req.Header.Set(echo.HeaderContentType, "application/pdf")
|
||||
// set custom headers (if any).
|
||||
customHTTPHeaders := resource.WebhookURLCustomHTTPHeaders(r)
|
||||
if len(customHTTPHeaders) > 0 {
|
||||
for key, value := range customHTTPHeaders {
|
||||
req.Header.Set(key, value)
|
||||
logger.DebugfOp(op, "set '%s' to custom HTTP header '%s'", value, key)
|
||||
}
|
||||
} else {
|
||||
logger.DebugOp(op, "skipping custom HTTP headers as none have been provided...")
|
||||
}
|
||||
// send the result file.
|
||||
logger.DebugfOp(
|
||||
op,
|
||||
"sending result file '%s' to '%s'...",
|
||||
filename,
|
||||
webhookURL,
|
||||
)
|
||||
resp, err := httpClient.Do(req) /* #nosec */
|
||||
if err != nil {
|
||||
xerr := xerror.New(op, err)
|
||||
logger.ErrorOp(xerror.Op(xerr), xerr)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close() // nolint: errcheck
|
||||
logger.DebugfOp(
|
||||
op,
|
||||
"result file '%s' sent to '%s'",
|
||||
filename,
|
||||
webhookURL,
|
||||
)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -581,11 +581,18 @@ func TestOfficeHandler(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWebhook(t *testing.T) {
|
||||
customHeaderRealKey := http.CanonicalHeaderKey("MyCustomHeader")
|
||||
customHeaderKey := fmt.Sprintf("%s%s", resource.WebhookURLCustomHTTPHeaderCanonicalBaseKey, customHeaderRealKey)
|
||||
customHeaderValue := "foo"
|
||||
status := make(chan error, 2)
|
||||
rcv := echo.New()
|
||||
rcv.POST("/foo", func(c echo.Context) error {
|
||||
if c.Request().Header.Get("Content-type") != "application/pdf" {
|
||||
status <- fmt.Errorf("wrong Content-type: got %s want %s", c.Request().Header.Get("Content-type"), "application/pdf")
|
||||
if c.Request().Header.Get(echo.HeaderContentType) != "application/pdf" {
|
||||
status <- fmt.Errorf("wrong Content-type: got '%s' want '%s'", c.Request().Header.Get(echo.HeaderContentType), "application/pdf")
|
||||
return nil
|
||||
}
|
||||
if c.Request().Header.Get(customHeaderRealKey) != customHeaderValue {
|
||||
status <- fmt.Errorf("wrong '%s': got '%s' want '%s'", customHeaderRealKey, c.Request().Header.Get(customHeaderRealKey), customHeaderValue)
|
||||
return nil
|
||||
}
|
||||
body, err := ioutil.ReadAll(c.Request().Body)
|
||||
@@ -609,6 +616,7 @@ func TestWebhook(t *testing.T) {
|
||||
body, contentType := test.MergeMultipartForm(t, map[string]string{string(resource.WebhookURLArgKey): "http://localhost:3001/foo"})
|
||||
req := httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
req.Header.Set(customHeaderKey, customHeaderValue)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
err := <-status
|
||||
assert.NoError(t, err)
|
||||
@@ -622,5 +630,5 @@ func TestResultFilename(t *testing.T) {
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
rec := httptest.NewRecorder()
|
||||
srv.ServeHTTP(rec, req)
|
||||
assert.Equal(t, "attachment; filename=\"foo.pdf\"", rec.Header().Get("Content-Disposition"))
|
||||
assert.Equal(t, "attachment; filename=\"foo.pdf\"", rec.Header().Get(echo.HeaderContentDisposition))
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/thecodingmachine/gotenberg/internal/app/xhttp/pkg/resource"
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/conf"
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/normalize"
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/xerror"
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/xlog"
|
||||
)
|
||||
@@ -79,6 +78,10 @@ func (ctx *Context) WithResource(directoryName string) error {
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
// retrieve custom headers from request.
|
||||
for key, value := range ctx.Request().Header {
|
||||
r.WithCustomHTTPHeader(key, value[0])
|
||||
}
|
||||
// retrieve form values from request.
|
||||
for _, key := range resource.ArgKeys() {
|
||||
r.WithArg(key, ctx.FormValue(string(key)))
|
||||
@@ -103,11 +106,7 @@ func (ctx *Context) WithResource(directoryName string) error {
|
||||
return r, err
|
||||
}
|
||||
defer in.Close() // nolint: errcheck
|
||||
filename, err := normalize.String(fh.Filename)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
if err := r.WithFile(filename, in); err != nil {
|
||||
if err := r.WithFile(fh.Filename, in); err != nil {
|
||||
return r, err
|
||||
}
|
||||
}
|
||||
|
||||
37
internal/app/xhttp/pkg/resource/header.go
Normal file
37
internal/app/xhttp/pkg/resource/header.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// RemoteURLCustomHTTPHeaderCanonicalBaseKey is the base key
|
||||
// of custom headers send to the remote URL.
|
||||
RemoteURLCustomHTTPHeaderCanonicalBaseKey string = "Gotenberg-Remoteurl-"
|
||||
// WebhookURLCustomHTTPHeaderCanonicalBaseKey is the base key
|
||||
// of custom headers send to the webhook URL.
|
||||
WebhookURLCustomHTTPHeaderCanonicalBaseKey string = "Gotenberg-Webhookurl-"
|
||||
)
|
||||
|
||||
func fetchCustomHTTPHeaders(r Resource, baseKey string) map[string]string {
|
||||
customHeaders := make(map[string]string)
|
||||
for key, value := range r.customHeaders {
|
||||
if strings.Contains(key, baseKey) {
|
||||
realKey := strings.Replace(key, baseKey, "", 1)
|
||||
customHeaders[realKey] = value
|
||||
}
|
||||
}
|
||||
return customHeaders
|
||||
}
|
||||
|
||||
// RemoteURLCustomHTTPHeaders is a helper for retrieving
|
||||
// the custom headers for the URL conversion.
|
||||
func RemoteURLCustomHTTPHeaders(r Resource) map[string]string {
|
||||
return fetchCustomHTTPHeaders(r, RemoteURLCustomHTTPHeaderCanonicalBaseKey)
|
||||
}
|
||||
|
||||
// WebhookURLCustomHTTPHeaders is a helper for retrieving
|
||||
// the custom headers for the webhook URL.
|
||||
func WebhookURLCustomHTTPHeaders(r Resource) map[string]string {
|
||||
return fetchCustomHTTPHeaders(r, WebhookURLCustomHTTPHeaderCanonicalBaseKey)
|
||||
}
|
||||
54
internal/app/xhttp/pkg/resource/header_test.go
Normal file
54
internal/app/xhttp/pkg/resource/header_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/thecodingmachine/gotenberg/test"
|
||||
)
|
||||
|
||||
func TestRemoteURLCustomHeaders(t *testing.T) {
|
||||
const resourceDirectoryName string = "foo"
|
||||
logger := test.DebugLogger()
|
||||
r, err := New(logger, resourceDirectoryName)
|
||||
assert.Nil(t, err)
|
||||
// should find the custom header.
|
||||
customHeaderValue := "bar"
|
||||
customHeaderCanonicalRealKey := "Foo"
|
||||
customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", RemoteURLCustomHTTPHeaderCanonicalBaseKey, customHeaderCanonicalRealKey))
|
||||
r.WithCustomHTTPHeader(customHeaderCanonicalKey, customHeaderValue)
|
||||
r.WithCustomHTTPHeader("Bar", "Bar")
|
||||
expected := map[string]string{
|
||||
customHeaderCanonicalRealKey: customHeaderValue,
|
||||
}
|
||||
notExpected := map[string]string{
|
||||
customHeaderCanonicalKey: customHeaderValue,
|
||||
}
|
||||
v := RemoteURLCustomHTTPHeaders(r)
|
||||
assert.Equal(t, expected, v)
|
||||
assert.NotEqual(t, notExpected, v)
|
||||
}
|
||||
|
||||
func TestWebhookURLCustomHeaders(t *testing.T) {
|
||||
const resourceDirectoryName string = "foo"
|
||||
logger := test.DebugLogger()
|
||||
r, err := New(logger, resourceDirectoryName)
|
||||
assert.Nil(t, err)
|
||||
// should find the custom header.
|
||||
customHeaderValue := "bar"
|
||||
customHeaderCanonicalRealKey := "Foo"
|
||||
customHeaderCanonicalKey := http.CanonicalHeaderKey(fmt.Sprintf("%s%s", WebhookURLCustomHTTPHeaderCanonicalBaseKey, customHeaderCanonicalRealKey))
|
||||
r.WithCustomHTTPHeader(customHeaderCanonicalKey, customHeaderValue)
|
||||
r.WithCustomHTTPHeader("Bar", "Bar")
|
||||
expected := map[string]string{
|
||||
customHeaderCanonicalRealKey: customHeaderValue,
|
||||
}
|
||||
notExpected := map[string]string{
|
||||
customHeaderCanonicalKey: customHeaderValue,
|
||||
}
|
||||
v := WebhookURLCustomHTTPHeaders(r)
|
||||
assert.Equal(t, expected, v)
|
||||
assert.NotEqual(t, notExpected, v)
|
||||
}
|
||||
@@ -3,9 +3,12 @@ package resource
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/normalize"
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/xassert"
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/xerror"
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/xlog"
|
||||
@@ -21,10 +24,11 @@ const TemporaryDirectory string = "tmp"
|
||||
// Resource helps managing
|
||||
// arguments and files for a conversion.
|
||||
type Resource struct {
|
||||
logger xlog.Logger
|
||||
dirPath string
|
||||
args map[ArgKey]string
|
||||
files map[string]file
|
||||
logger xlog.Logger
|
||||
dirPath string
|
||||
customHeaders map[string]string
|
||||
args map[ArgKey]string
|
||||
files map[string]file
|
||||
}
|
||||
|
||||
// New creates a Resource where its files will
|
||||
@@ -48,10 +52,11 @@ func New(logger xlog.Logger, directoryName string) (Resource, error) {
|
||||
}
|
||||
logger.DebugfOp(op, "resource directory '%s' created", directoryName)
|
||||
return Resource{
|
||||
logger: logger,
|
||||
dirPath: dirPath,
|
||||
args: make(map[ArgKey]string),
|
||||
files: make(map[string]file),
|
||||
logger: logger,
|
||||
dirPath: dirPath,
|
||||
customHeaders: make(map[string]string),
|
||||
args: make(map[ArgKey]string),
|
||||
files: make(map[string]file),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -70,6 +75,21 @@ func (r Resource) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithCustomHTTPHeader add a new custom header to the Resource.
|
||||
// Given key should be in canonical format.
|
||||
func (r *Resource) WithCustomHTTPHeader(key string, value string) {
|
||||
const op string = "resource.Resource.WithCustomHTTPHeader"
|
||||
// should already be in canonical format.
|
||||
canonicalKey := http.CanonicalHeaderKey(key)
|
||||
if strings.Contains(canonicalKey, RemoteURLCustomHTTPHeaderCanonicalBaseKey) ||
|
||||
strings.Contains(canonicalKey, WebhookURLCustomHTTPHeaderCanonicalBaseKey) {
|
||||
r.customHeaders[canonicalKey] = value
|
||||
r.logger.DebugfOp(op, "added '%s' with value '%s' to resource custom HTTP headers", canonicalKey, value)
|
||||
return
|
||||
}
|
||||
r.logger.DebugfOp(op, "skipping '%s' as it is not a custom HTTP header...", canonicalKey)
|
||||
}
|
||||
|
||||
// WithArg add a new argument to the Resource.
|
||||
func (r *Resource) WithArg(key ArgKey, value string) {
|
||||
const op string = "resource.Resource.WithArg"
|
||||
@@ -80,13 +100,24 @@ func (r *Resource) WithArg(key ArgKey, value string) {
|
||||
// WithFile add a new file to the Resource.
|
||||
func (r *Resource) WithFile(filename string, in io.Reader) error {
|
||||
const op string = "resource.Resource.WithFile"
|
||||
fpath := fmt.Sprintf("%s/%s", r.dirPath, filename)
|
||||
file := file{fpath: fpath}
|
||||
if err := file.write(in); err != nil {
|
||||
resolver := func() error {
|
||||
// see https://github.com/thecodingmachine/gotenberg/issues/104.
|
||||
normalized, err := normalize.String(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fpath := fmt.Sprintf("%s/%s", r.dirPath, normalized)
|
||||
file := file{fpath: fpath}
|
||||
if err := file.write(in); err != nil {
|
||||
return err
|
||||
}
|
||||
r.files[filename] = file
|
||||
r.logger.DebugfOp(op, "resource file '%s' created", filename)
|
||||
return nil
|
||||
}
|
||||
if err := resolver(); err != nil {
|
||||
return xerror.New(op, err)
|
||||
}
|
||||
r.files[filename] = file
|
||||
r.logger.DebugfOp(op, "resource file '%s' created", filename)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package printer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
@@ -30,18 +31,19 @@ type chromePrinter struct {
|
||||
// ChromePrinterOptions helps customizing the
|
||||
// Google Chrome Printer behaviour.
|
||||
type ChromePrinterOptions struct {
|
||||
WaitTimeout float64
|
||||
WaitDelay float64
|
||||
HeaderHTML string
|
||||
FooterHTML string
|
||||
PaperWidth float64
|
||||
PaperHeight float64
|
||||
MarginTop float64
|
||||
MarginBottom float64
|
||||
MarginLeft float64
|
||||
MarginRight float64
|
||||
Landscape bool
|
||||
RpccBufferSize int64
|
||||
WaitTimeout float64
|
||||
WaitDelay float64
|
||||
HeaderHTML string
|
||||
FooterHTML string
|
||||
PaperWidth float64
|
||||
PaperHeight float64
|
||||
MarginTop float64
|
||||
MarginBottom float64
|
||||
MarginLeft float64
|
||||
MarginRight float64
|
||||
Landscape bool
|
||||
RpccBufferSize int64
|
||||
CustomHTTPHeaders map[string]string
|
||||
}
|
||||
|
||||
// DefaultChromePrinterOptions returns the default
|
||||
@@ -49,18 +51,19 @@ type ChromePrinterOptions struct {
|
||||
func DefaultChromePrinterOptions(config conf.Config) ChromePrinterOptions {
|
||||
const defaultHeaderFooterHTML string = "<html><head></head><body></body></html>"
|
||||
return ChromePrinterOptions{
|
||||
WaitTimeout: config.DefaultWaitTimeout(),
|
||||
WaitDelay: 0.0,
|
||||
HeaderHTML: defaultHeaderFooterHTML,
|
||||
FooterHTML: defaultHeaderFooterHTML,
|
||||
PaperWidth: 8.27,
|
||||
PaperHeight: 11.7,
|
||||
MarginTop: 1.0,
|
||||
MarginBottom: 1.0,
|
||||
MarginLeft: 1.0,
|
||||
MarginRight: 1.0,
|
||||
Landscape: false,
|
||||
RpccBufferSize: config.DefaultGoogleChromeRpccBufferSize(),
|
||||
WaitTimeout: config.DefaultWaitTimeout(),
|
||||
WaitDelay: 0.0,
|
||||
HeaderHTML: defaultHeaderFooterHTML,
|
||||
FooterHTML: defaultHeaderFooterHTML,
|
||||
PaperWidth: 8.27,
|
||||
PaperHeight: 11.7,
|
||||
MarginTop: 1.0,
|
||||
MarginBottom: 1.0,
|
||||
MarginLeft: 1.0,
|
||||
MarginRight: 1.0,
|
||||
Landscape: false,
|
||||
RpccBufferSize: config.DefaultGoogleChromeRpccBufferSize(),
|
||||
CustomHTTPHeaders: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +147,10 @@ func (p chromePrinter) Print(destination string) error {
|
||||
if err := p.enableEvents(ctx, targetClient); err != nil {
|
||||
return err
|
||||
}
|
||||
// add custom headers (if any).
|
||||
if err := p.setCustomHTTPHeaders(ctx, targetClient); err != nil {
|
||||
return err
|
||||
}
|
||||
// listen for all events.
|
||||
if err := p.listenEvents(ctx, targetClient); err != nil {
|
||||
return err
|
||||
@@ -247,6 +254,32 @@ func (p chromePrinter) enableEvents(ctx context.Context, client *cdp.Client) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p chromePrinter) setCustomHTTPHeaders(ctx context.Context, client *cdp.Client) error {
|
||||
const op string = "printer.chromePrinter.setCustomHTTPHeaders"
|
||||
resolver := func() error {
|
||||
if len(p.opts.CustomHTTPHeaders) == 0 {
|
||||
p.logger.DebugOp(op, "skipping custom HTTP headers as none have been provided...")
|
||||
return nil
|
||||
}
|
||||
customHTTPHeaders := make(map[string]string)
|
||||
// useless but for the logs.
|
||||
for key, value := range p.opts.CustomHTTPHeaders {
|
||||
customHTTPHeaders[key] = value
|
||||
p.logger.DebugfOp(op, "set '%s' to custom HTTP header '%s'", value, key)
|
||||
}
|
||||
b, err := json.Marshal(customHTTPHeaders)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// should always be called after client.Network.Enable.
|
||||
return client.Network.SetExtraHTTPHeaders(ctx, network.NewSetExtraHTTPHeadersArgs(b))
|
||||
}
|
||||
if err := resolver(); err != nil {
|
||||
return xerror.New(op, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p chromePrinter) listenEvents(ctx context.Context, client *cdp.Client) error {
|
||||
const op string = "printer.chromePrinter.listenEvents"
|
||||
resolver := func() error {
|
||||
|
||||
@@ -79,7 +79,7 @@ func multipartForm(
|
||||
require.Nil(t, err)
|
||||
}
|
||||
if kind == "url" {
|
||||
err := writer.WriteField("remoteURL", "http://google.com")
|
||||
err := writer.WriteField("remoteURL", "https://google.com")
|
||||
require.Nil(t, err)
|
||||
}
|
||||
for k, v := range formValues {
|
||||
|
||||
@@ -75,6 +75,7 @@ func OfficeFpaths(t *testing.T) []string {
|
||||
fpath(t, "office", "document.docx"),
|
||||
fpath(t, "office", "document.rtf"),
|
||||
fpath(t, "office", "document.txt"),
|
||||
fpath(t, "office", "document_with_special_éà.txt"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
test/testdata/office/document_with_special_éà.txt
vendored
Normal file
3
test/testdata/office/document_with_special_éà.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Gutenberg
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
Reference in New Issue
Block a user