Skip to content

Commit adc1227

Browse files
committed
Merge branch 'release/2.1.0' into master
2 parents e6b9148 + c4621e2 commit adc1227

78 files changed

Lines changed: 3290 additions & 1886 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

GotenbergSharpApiClient.sln.DotSettings

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue"> Copyright 2019-$CURRENT_YEAR$ Chris Mohan, Jaben Cargman&#xD;
3+
and GotenbergSharpApiClient Contributors&#xD;
4+
&#xD;
5+
Licensed under the Apache License, Version 2.0 (the "License");&#xD;
6+
you may not use this file except in compliance with the License.&#xD;
7+
You may obtain a copy of the License at&#xD;
8+
&#xD;
9+
http://www.apache.org/licenses/LICENSE-2.0&#xD;
10+
&#xD;
11+
Unless required by applicable law or agreed to in writing, software&#xD;
12+
distributed under the License is distributed on an "AS IS" BASIS,&#xD;
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#xD;
14+
See the License for the specific language governing permissions and&#xD;
15+
limitations under the License.</s:String>
216
<s:Boolean x:Key="/Default/UserDictionary/Words/=Backoff/@EntryIndexedValue">True</s:Boolean>
317
<s:Boolean x:Key="/Default/UserDictionary/Words/=Consts/@EntryIndexedValue">True</s:Boolean>
418
<s:Boolean x:Key="/Default/UserDictionary/Words/=deliverables/@EntryIndexedValue">True</s:Boolean>

README.md

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# <img src="https://github.com/ChangemakerStudios/GotenbergSharpApiClient/raw/master/lib/Resources/gotenbergSharpClient.PNG" width="24" height="24" /> Gotenberg.Sharp.Api.Client
1+
# ![gotenberg icon](https://raw.githubusercontent.com/ChangemakerStudios/GotenbergSharpApiClient/develop/lib/Resources/gotenbergSharpClient.PNG) Gotenberg.Sharp.Api.Client
22

33
[![NuGet version](https://badge.fury.io/nu/Gotenberg.Sharp.Api.Client.svg)](https://badge.fury.io/nu/Gotenberg.Sharp.Api.Client)
44
[![Downloads](https://img.shields.io/nuget/dt/Gotenberg.Sharp.API.Client.svg?logo=nuget&color=purple)](https://www.nuget.org/packages/Gotenberg.Sharp.API.Client)
@@ -8,7 +8,6 @@
88

99
.NET C# Client for interacting with the [Gotenberg](https://gotenberg.dev/) v7 micro-service's API. [Gotenberg](https://github.com/gotenberg/gotenberg) is a [Docker-powered stateless API](https://hub.docker.com/r/gotenberg/gotenberg/) for converting & merging HTML, Markdown and Office documents to PDF. The client supports a configurable [Polly](http://www.thepollyproject.org/) **retry policy** with exponential backoff for handling transient exceptions.
1010

11-
1211
# Getting Started
1312
*Pull the image from dockerhub.com*
1413
```powershell
@@ -53,12 +52,10 @@ public void ConfigureServices(IServiceCollection services)
5352
}
5453

5554
```
56-
# Using GotenbergSharpClient.
55+
# Using GotenbergSharpClient
5756
*See the [linqPad folder](linqpad/)* for complete examples.
5857

59-
### Note: Samples below are currently stale. Linqpad scripts are fresh.
60-
61-
## Html To Pdf
58+
### Html To Pdf
6259
*With embedded assets:*
6360

6461
```csharp
@@ -83,7 +80,7 @@ public void ConfigureServices(IServiceCollection services)
8380
}
8481
```
8582

86-
## Url To Pdf
83+
### Url To Pdf
8784
*Url to Pdf with custom page range, header & footer:*
8885

8986
```csharp
@@ -93,7 +90,7 @@ public async Task<Stream> CreateFromUrl(string headerPath, string footerPath)
9390
.SetUrl("https://www.cnn.com")
9491
.ConfigureRequest(config =>
9592
{
96-
config.PageRanges("1-2");
93+
config.SetPageRanges("1-2");
9794
})
9895
.AddAsyncHeaderFooter(async
9996
doc => doc.SetHeader(await File.ReadAllTextAsync(headerPath))
@@ -123,7 +120,7 @@ public async Task<Stream> DoOfficeMerge(string sourceDirectory)
123120
return await _sharpClient.MergeOfficeDocsAsync(request);
124121
}
125122
```
126-
## Markdown to Pdf
123+
### Markdown to Pdf
127124
*Markdown to Pdf conversion with embedded assets:*
128125

129126
```csharp
@@ -146,7 +143,7 @@ public async Task<Stream> CreateFromMarkdown()
146143
return await _sharpClient.HtmlToPdfAsync(request);
147144
}
148145
```
149-
## Webhook
146+
### Webhook
150147
*All request types support webhooks*
151148

152149
```csharp
@@ -158,11 +155,11 @@ public async Task<Stream> CreateFromMarkdown()
158155
{
159156
reqBuilder.AddWebhook(hook =>
160157
{
161-
hook.SetTimeout(20)
162-
.SetUrl("http://host.docker.internal:5000/api/your/webhookReceiver")
163-
.AddRequestHeader("custom-header", "value");
158+
hook.SetUrl("http://host.docker.internal:5000/api/your/webhookReceiver")
159+
.SetErrorUrl("http://host.docker.internal:5000/api/your/webhookReceiver/error")
160+
.AddExtraHeader("custom-header", "value");
164161
})
165-
.PageRanges("1-2");
162+
.SetPageRanges("1-2");
166163
})
167164
.AddAsyncHeaderFooter(async
168165
b => b.SetHeader(await System.IO.File.ReadAllTextAsync(headerPath))
@@ -181,7 +178,7 @@ public async Task<Stream> CreateFromMarkdown()
181178
}
182179

183180
```
184-
## Merge 15 Urls to one pdf
181+
### Merge 15 Urls to one pdf
185182
*Builds a 30 page pdf by merging the front two pages of 15 news sites. Takes about a minute to complete*
186183

187184
```csharp
@@ -210,8 +207,7 @@ IEnumerable<UrlRequestBuilder> CreateBuilders(IEnumerable<Uri> uris)
210207
{
211208
yield return new UrlRequestBuilder()
212209
.SetUrl(uri)
213-
.SetRemoteUrlHeader("gotenberg-sharp-news-summary", $"{DateTime.Now.ToShortDateString()}")
214-
.ConfigureRequest(req => { req.PageRanges("1-2"); })
210+
.ConfigureRequest(req => { req.SetPageRanges("1-2"); })
215211
.AddHeaderFooter(docBuilder =>
216212
{
217213
docBuilder.SetHeader(GetHeadFoot(uri.Host.Replace("www.", string.Empty).ToUpper()))

lib/Domain/Builders/BaseBuilder.cs

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,80 @@
1-
using System;
1+
// Copyright 2019-2022 Chris Mohan, Jaben Cargman
2+
// and GotenbergSharpApiClient Contributors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Linq;
19+
using System.Threading.Tasks;
220

321
using Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;
422
using Gotenberg.Sharp.API.Client.Domain.Requests;
523
using Gotenberg.Sharp.API.Client.Domain.Requests.Facets;
624

725
using JetBrains.Annotations;
826

9-
namespace Gotenberg.Sharp.API.Client.Domain.Builders
27+
namespace Gotenberg.Sharp.API.Client.Domain.Builders;
28+
29+
public abstract class BaseBuilder<TRequest, TBuilder>
30+
where TRequest : BuildRequestBase
31+
where TBuilder : BaseBuilder<TRequest, TBuilder>
1032
{
11-
public abstract class BaseBuilder<TRequest, TBuilder>
12-
where TRequest : RequestBase
13-
where TBuilder : BaseBuilder<TRequest, TBuilder>
33+
protected BaseBuilder(TRequest request)
34+
{
35+
this.Request = request;
36+
}
37+
38+
protected const string CallBuildAsyncErrorMessage =
39+
"Request has asynchronous items. Call BuildAsync instead.";
40+
41+
protected readonly List<Task> BuildTasks = new();
42+
43+
protected virtual TRequest Request { get; }
44+
45+
[PublicAPI]
46+
public TBuilder ConfigureRequest(Action<ConfigBuilder> action)
1447
{
15-
protected virtual TRequest Request { get; set; }
16-
17-
protected const string CallBuildAsyncErrorMessage = "Request has asynchronous items. Call BuildAsync instead.";
18-
19-
[PublicAPI]
20-
public TBuilder ConfigureRequest(Action<ConfigBuilder> action)
21-
{
22-
if (action == null) throw new ArgumentNullException(nameof(action));
23-
action(new ConfigBuilder(this.Request));
24-
return (TBuilder) this;
25-
}
26-
27-
[PublicAPI]
28-
public TBuilder ConfigureRequest(RequestConfig config)
29-
{
30-
this.Request.Config = config ?? throw new ArgumentNullException(nameof(config));
31-
return (TBuilder) this;
32-
}
48+
if (action == null) throw new ArgumentNullException(nameof(action));
49+
50+
this.Request.Config ??= new RequestConfig();
51+
52+
action(new ConfigBuilder(this.Request.Config));
53+
54+
return (TBuilder)this;
55+
}
56+
57+
[PublicAPI]
58+
public TBuilder ConfigureRequest(RequestConfig config)
59+
{
60+
this.Request.Config = config ?? throw new ArgumentNullException(nameof(config));
61+
62+
return (TBuilder)this;
63+
}
64+
65+
[PublicAPI]
66+
public virtual TRequest Build()
67+
{
68+
if (this.BuildTasks.Any()) throw new InvalidOperationException(CallBuildAsyncErrorMessage);
69+
70+
return this.Request;
71+
}
72+
73+
[PublicAPI]
74+
public virtual async Task<TRequest> BuildAsync()
75+
{
76+
if (this.BuildTasks.Any()) await Task.WhenAll(this.BuildTasks).ConfigureAwait(false);
77+
78+
return this.Request;
3379
}
3480
}
Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
1-
using System;
2-
using System.Collections.Generic;
1+
// Copyright 2019-2022 Chris Mohan, Jaben Cargman
2+
// and GotenbergSharpApiClient Contributors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
using System;
317
using System.Threading.Tasks;
418

519
using Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;
@@ -14,52 +28,61 @@ public abstract class BaseChromiumBuilder<TRequest, TBuilder> : BaseBuilder<TReq
1428
where TRequest : ChromeRequest
1529
where TBuilder : BaseChromiumBuilder<TRequest, TBuilder>
1630
{
17-
protected readonly List<Task> AsyncTasks = new List<Task>();
31+
protected BaseChromiumBuilder([NotNull] TRequest request)
32+
: base(request)
33+
{
34+
}
1835

1936
[PublicAPI]
2037
public TBuilder WithDimensions(Action<DimensionBuilder> action)
2138
{
2239
if (action == null) throw new ArgumentNullException(nameof(action));
2340

24-
action(new DimensionBuilder(this.Request));
25-
return (TBuilder) this;
41+
var builder = new DimensionBuilder(this.Request.Dimensions);
42+
43+
action(builder);
44+
45+
this.Request.Dimensions = builder.GetDimensions();
46+
47+
return (TBuilder)this;
2648
}
2749

2850
[PublicAPI]
2951
public TBuilder WithDimensions(Dimensions dimensions)
3052
{
3153
this.Request.Dimensions = dimensions ?? throw new ArgumentNullException(nameof(dimensions));
32-
return (TBuilder) this;
54+
return (TBuilder)this;
3355
}
3456

3557
[PublicAPI]
3658
public TBuilder WithAssets(Action<AssetBuilder> action)
3759
{
3860
if (action == null) throw new ArgumentNullException(nameof(action));
39-
action(new AssetBuilder(this.Request));
40-
return (TBuilder) this;
61+
action(new AssetBuilder(this.Request.Assets ??= new AssetDictionary()));
62+
return (TBuilder)this;
4163
}
4264

4365
[PublicAPI]
4466
public TBuilder WithAsyncAssets(Func<AssetBuilder, Task> asyncAction)
4567
{
4668
if (asyncAction == null) throw new ArgumentNullException(nameof(asyncAction));
47-
this.AsyncTasks.Add(asyncAction(new AssetBuilder(this.Request)));
48-
return (TBuilder) this;
69+
this.BuildTasks.Add(asyncAction(new AssetBuilder(this.Request.Assets ??= new AssetDictionary())));
70+
return (TBuilder)this;
4971
}
5072

5173
[PublicAPI]
5274
public TBuilder SetConversionBehaviors(Action<HtmlConversionBehaviorBuilder> action)
5375
{
5476
if (action == null) throw new ArgumentNullException(nameof(action));
55-
action(new HtmlConversionBehaviorBuilder(this.Request));
56-
return (TBuilder) this;
77+
action(new HtmlConversionBehaviorBuilder(this.Request.ConversionBehaviors));
78+
return (TBuilder)this;
5779
}
5880

5981
[PublicAPI]
6082
public TBuilder SetConversionBehaviors(HtmlConversionBehaviors behaviors)
6183
{
62-
this.Request.ConversionBehaviors = behaviors ?? throw new ArgumentNullException(nameof(behaviors));
63-
return (TBuilder) this;
84+
this.Request.ConversionBehaviors =
85+
behaviors ?? throw new ArgumentNullException(nameof(behaviors));
86+
return (TBuilder)this;
6487
}
65-
}
88+
}

0 commit comments

Comments
 (0)