Added ln.patterns, introduced usage of Optional<> for better exception description via http

master
Harald Wolff 2023-08-14 14:24:09 +02:00
parent d30f8c6576
commit c0f39a81a8
6 changed files with 97 additions and 53 deletions

View File

@ -4,6 +4,7 @@ using Jint;
using Jint.Native;
using Jint.Native.Json;
using Jint.Native.Object;
using Jint.Runtime;
using ln.http;
using ln.json;
using ln.json.mapping;
@ -61,8 +62,17 @@ namespace ln.templates.service
)
{
ObjectInstance jsonObject = new JsonParser(new Engine()).Parse(postContent) as ObjectInstance;
if (_templateService.RenderTemplate(templatePath, jsonObject, out Stream templateStream))
return HttpResponse.OK().ContentType("text/html").Content(templateStream);
var templateStream = _templateService.RenderTemplate(templatePath, jsonObject);
if (templateStream)
return HttpResponse.OK().ContentType("text/html").Content(templateStream.Value);
if (templateStream.Is(out FileNotFoundException e))
return HttpResponse.NotFound().Content(e.FileName);
if (templateStream.Is(out JavaScriptException jse))
return HttpResponse.BadRequest()
.Content(String.Format("JavaScript exception: {0}", jse.Error.ToString()));
return HttpResponse.InternalServerError();
}
@ -74,8 +84,16 @@ namespace ln.templates.service
)
{
ObjectInstance jsonObject = new JsonParser(new Engine()).Parse(postContent) as ObjectInstance;
if (_templateService.RenderPDF(templatePath, jsonObject, out Stream templateStream))
return HttpResponse.OK().ContentType("application/pdf").Content(templateStream);
var pdfStream = _templateService.RenderPDF(templatePath, jsonObject);
if (pdfStream)
return HttpResponse.OK().ContentType("application/pdf").Content(pdfStream.Value);
if (pdfStream.Is(out FileNotFoundException e))
return HttpResponse.NotFound().Content(e.FileName);
if (pdfStream.Is(out JavaScriptException jse))
return HttpResponse.BadRequest()
.Content(String.Format("JavaScript exception: {0}", jse.Error.ToString()));
return HttpResponse.InternalServerError();
}

View File

@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using Jint.Native;
using Jint.Native.Object;
using ln.patterns;
using ln.templates.service.render;
namespace ln.templates.service
@ -121,48 +121,64 @@ namespace ln.templates.service
}
public bool RenderTemplate(string templatePath, ObjectInstance o, out Stream templateStream)
=> RenderTemplate(templatePath, o).TryGetValue(out templateStream);
public Optional<Stream> RenderTemplate(string templatePath, ObjectInstance o)
{
if (templatePath is null)
throw new NullReferenceException();
string directoryPath = Path.GetDirectoryName(templatePath);
string templateFilename = Path.GetFileName(templatePath);
var resolver = Resolver
.FindResolver(directoryPath);
if (resolver is null)
return new FileNotFoundException("", directoryPath);
Template template = resolver.GetTemplate(templateFilename);
if (template is null)
return new FileNotFoundException("", templatePath);
TempFileStream tempFileStream = new TempFileStream(".html");
Template template = Resolver
.FindResolver(directoryPath)
.GetTemplate(templateFilename);
Context context = new Context(template.Resolver, new StreamWriter(tempFileStream));
context.Engine.Realm.GlobalEnv.SetMutableBinding("$baseurl", String.Format("file://{0}",Path.Combine(StoragePath, "resources/")), false);
template.Render(context, o);
try
{
template.Render(context, o);
}
catch (Exception e)
{
return e;
}
tempFileStream.Position = 0;
templateStream = tempFileStream;
return true;
return tempFileStream;
}
public bool RenderPDF(string templatePath, ObjectInstance o, out Stream targetStream)
public bool RenderPDF(string templatePath, ObjectInstance o, out Stream targetStream) =>
RenderPDF(templatePath, o).TryGetValue(out targetStream);
public Optional<Stream> RenderPDF(string templatePath, ObjectInstance o)
{
if (templatePath is null)
throw new NullReferenceException();
string directoryPath = Path.GetDirectoryName(templatePath);
string templateFilename = Path.GetFileName(templatePath);
TempFileStream tempFileStream = new TempFileStream(".html");
Template template = Resolver
.FindResolver(directoryPath)
.GetTemplate(templateFilename);
var resolver = Resolver
.FindResolver(directoryPath);
if (resolver is null)
return new FileNotFoundException("", directoryPath);
Template template = resolver.GetTemplate(templateFilename);
if (template is null)
return new FileNotFoundException("", templatePath);
return PuppeteerRenderer.RenderTemplate(
template,
String.Format("file://{0}", Path.Combine(StoragePath, "resources/")),
o,
out targetStream
o
);
}

View File

@ -4,7 +4,7 @@
<OutputType>Exe</OutputType>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net6.0;net5.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
@ -15,6 +15,7 @@
<PackageReference Include="ln.bootstrap" Version="1.5.0-preview0" />
<PackageReference Include="ln.http" Version="0.9.7-test0" />
<PackageReference Include="ln.json" Version="1.2.4" />
<PackageReference Include="ln.patterns" Version="0.1.0-preview6" />
<PackageReference Include="PuppeteerSharp" Version="10.1.2" />
</ItemGroup>
@ -61,4 +62,6 @@
<Folder Include="storage\" />
</ItemGroup>
</Project>

View File

@ -1,5 +1,7 @@
using System;
using System.IO;
using Jint.Native.Object;
using ln.patterns;
using PuppeteerSharp;
namespace ln.templates.service.render
@ -8,27 +10,28 @@ namespace ln.templates.service.render
{
private static BrowserFetcher _browserFetcher;
public static bool RenderTemplate(Template template, string resourcePath, ObjectInstance globals,
out Stream pdfStream)
public static Optional<Stream> RenderTemplate(Template template, string resourcePath, ObjectInstance globals)
{
using (StringWriter htmlWriter = new StringWriter())
{
Context context = new Context(template.Resolver, htmlWriter);
template.Render(context, globals);
using (var browser = Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
}).Result)
try
{
using (var page = browser.NewPageAsync().Result)
Context context = new Context(template.Resolver, htmlWriter);
template.Render(context, globals);
using (var browser = Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
}).Result)
{
page.GoToAsync(resourcePath).Wait();
page.SetContentAsync(htmlWriter.ToString(),new NavigationOptions()
using (var page = browser.NewPageAsync().Result)
{
}).Wait();
var footerTemplate = page.EvaluateFunctionAsync<string>($@"()=>{{
page.GoToAsync(resourcePath).Wait();
page.SetContentAsync(htmlWriter.ToString(), new NavigationOptions()
{
}).Wait();
var footerTemplate = page.EvaluateFunctionAsync<string>($@"()=>{{
let footers = document.getElementsByTagName('footer');
if (footers.length){{
let footerHtml = footers[0].outerHTML;
@ -37,21 +40,25 @@ if (footers.length){{
}}
return null;
}}").Result;
page.SetContentAsync(page.GetContentAsync().Result).Wait();
TempFileStream pdfTempStream = new TempFileStream(".pdf");
page.PdfAsync(pdfTempStream.Name, new PdfOptions()
{
HeaderTemplate = "<div></div>",
FooterTemplate = footerTemplate,
DisplayHeaderFooter = true,
}).Wait();
pdfStream = pdfTempStream;
return true;
page.SetContentAsync(page.GetContentAsync().Result).Wait();
TempFileStream pdfTempStream = new TempFileStream(".pdf");
page.PdfAsync(pdfTempStream.Name, new PdfOptions()
{
HeaderTemplate = "<div></div>",
FooterTemplate = footerTemplate,
DisplayHeaderFooter = true,
}).Wait();
return pdfTempStream;
}
}
}
catch (Exception e)
{
return e;
}
}
}

View File

@ -4,7 +4,7 @@
<IsPackable>false</IsPackable>
<TargetFrameworks>net5.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<LangVersion>default</LangVersion>
</PropertyGroup>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<PackageVersion>0.4.2</PackageVersion>
<TargetFrameworks>net5.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<LangVersion>default</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>