<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel Reis</title>
    <description>The latest articles on DEV Community by Daniel Reis (@danspark).</description>
    <link>https://dev.to/danspark</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F285406%2Ff519c777-fb78-4eac-b52b-df9f9e604f6f.png</url>
      <title>DEV Community: Daniel Reis</title>
      <link>https://dev.to/danspark</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danspark"/>
    <language>en</language>
    <item>
      <title>Running Azure Functions with .NET 5 on Docker</title>
      <dc:creator>Daniel Reis</dc:creator>
      <pubDate>Fri, 13 Aug 2021 02:11:46 +0000</pubDate>
      <link>https://dev.to/danspark/running-azure-functions-with-net-5-on-docker-1b07</link>
      <guid>https://dev.to/danspark/running-azure-functions-with-net-5-on-docker-1b07</guid>
      <description>&lt;p&gt;The  &lt;a href="https://github.com/Azure/azure-functions-dotnet-worker"&gt;Azure Functions .NET worker&lt;/a&gt; has been out for a while, and it finally enabled developers to use C# 9 and .NET 5 on function apps. This is a new way to create C# function apps, it now has a &lt;code&gt;Program.cs&lt;/code&gt; class, with the good old generic Host builder and all the extension methods that we're used to see on regular ASP.NET Core and Worker service projects. This is how it can look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Configuration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Hosting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HostBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAppConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"appsettings.json"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureFunctionsWorkerDefaults&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this is using &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/top-level-statements"&gt;top-level statements&lt;/a&gt;. This came with C# 9 and it basically hides the Program class and its namespace, removing some boilerplate and making it easier to understand for newcomers, looks nice!&lt;/p&gt;

&lt;p&gt;If you want to run the .NET 5 function apps on Docker containers, as of the day of writing this, the Dockerfile generated by &lt;code&gt;func init --docker --worker-runtime dotnetIsolated&lt;/code&gt; does not build correctly, you'll encounter the following error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The framework 'Microsoft.NETCore.App', version '3.1.0' was not found.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is because  &lt;a href="https://github.com/Azure/azure-functions-dotnet-worker/issues/297"&gt;you'll still need .NET Core 3.1 installed&lt;/a&gt;  for it to work. I don't know why this wasn't fixed in the core tools template, but until it's fixed, you can use the following workaround: copying the 3.1 SDK into the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM mcr.microsoft.com/dotnet/sdk:5.0 AS installer-env
# Add the line below and it'll build successfully
COPY --from=mcr.microsoft.com/dotnet/sdk:3.1 /usr/share/dotnet /usr/share/dotnet

COPY . /src/dotnet-function-app
RUN cd /src/dotnet-function-app &amp;amp;&amp;amp; \
    mkdir -p /home/site/wwwroot &amp;amp;&amp;amp; \
    dotnet publish src/functions/*.csproj --output /home/site/wwwroot

# To enable ssh &amp;amp; remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/dotnet-isolated:3.0-dotnet-isolated5.0-appservice
FROM mcr.microsoft.com/azure-functions/dotnet-isolated:3.0-dotnet-isolated5.0
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will hopefully get fixed soon, it's very weird to see a build error on a template like this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important: HTTP trigger authorization on Docker containers
&lt;/h2&gt;

&lt;p&gt;If you're going to use Docker containers to run your function apps, you'll get 401 responses when testing your HTTP functions, there's a nice blog post by Martin Björkström explaining how to solve this problem, &lt;a href="https://martinbjorkstrom.com/posts/2020-02-12-testing-protected-azure-functions"&gt;check it out&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>docker</category>
      <category>azure</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Add authorization to your Azure Functions with Static Web Apps</title>
      <dc:creator>Daniel Reis</dc:creator>
      <pubDate>Thu, 25 Feb 2021 05:35:15 +0000</pubDate>
      <link>https://dev.to/danspark/add-authorization-to-your-azure-functions-with-static-web-apps-23p4</link>
      <guid>https://dev.to/danspark/add-authorization-to-your-azure-functions-with-static-web-apps-23p4</guid>
      <description>&lt;p&gt;Recently, the Azure Static Web Apps team released some changes to allow us to better configure our app. Although this came with some breaking changes, we are now able to simplify our routes' authorization config! I've been waiting for this for a while, I created &lt;a href="https://github.com/Azure/static-web-apps/issues/132" rel="noopener noreferrer"&gt;an issue&lt;/a&gt; about this on August last year.&lt;/p&gt;

&lt;p&gt;If you need any guidance on creating a Static Web App with functions, you can check out my other blog post: &lt;a href="https://blog.danielreis.dev/using-function-proxies-with-azure-static-web-apps" rel="noopener noreferrer"&gt;Using function proxies with Azure Static Web Apps&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it worked before
&lt;/h2&gt;

&lt;p&gt;Previously, to add authorization to your SWA, you had to create a file named &lt;em&gt;routes.json&lt;/em&gt; in the root of your app's build artifact folder. That generally changes from framework to framework,  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/routes#location" rel="noopener noreferrer"&gt;but this is well documented&lt;/a&gt;. On the file, you can define routes that are authorized based on a user role. The default roles in a Static Web App are &lt;code&gt;anonymous&lt;/code&gt; (Someone who is not logged in) and &lt;code&gt;authenticated&lt;/code&gt; (Someone who is logged in through any of the identity providers). This is how a &lt;em&gt;routes.json&lt;/em&gt; file with authorization rules generally looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/index.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"allowedRoles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"authenticated"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file above says that to access &lt;strong&gt;any&lt;/strong&gt; page, you have to be logged on. You can specify which routes require an user to be authenticated so you could, for example, allow any user to access your app's front page, but to access the user panel he would have to be logged on.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works now
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;routes&lt;/code&gt; part of the file is mainly the same, with some fields renamed. The main breaking change is that there's a new file named &lt;em&gt;staticwebapp.config.json&lt;/em&gt;. It has the same capabilities of the &lt;em&gt;routes.json&lt;/em&gt; and more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can now define HTTP methods on your route definitions. Before, if you wanted to allow unauthenticated &lt;em&gt;GET&lt;/em&gt; requests but require authentication for &lt;em&gt;POST&lt;/em&gt; or &lt;em&gt;PUT&lt;/em&gt;, you had to define a different route for the &lt;em&gt;POST&lt;/em&gt; and &lt;em&gt;PUT&lt;/em&gt; routes. Now, you can use the same route and specify the HTTP methods on the &lt;code&gt;methods&lt;/code&gt; field. Here's an example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"methods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PUT"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowedRoles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"authenticated"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON above says that every route starting with &lt;code&gt;/api&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; the method is &lt;em&gt;POST&lt;/em&gt; or &lt;em&gt;PUT&lt;/em&gt; should only be called by users with the &lt;code&gt;authenticated&lt;/code&gt; role.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The &lt;code&gt;methods&lt;/code&gt; field works on the &lt;em&gt;routes.json&lt;/em&gt; file, but if you're starting a new application or modifying your routes file to use the new features, you should consider switching to the new file, since the old one is deprecated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Custom roles
&lt;/h2&gt;

&lt;p&gt;Azure Static Web Apps allow you to create custom roles to your users. Currently this is only possible when inviting users through the portal and it requires you to specify the Auth provider, email address, the apps's domain (for some reason) and the expiration (in hours, max 7 days), as well as the role name, of course. As far as I know, there's no way to do this outside the portal, but hopefully this will change in the future. You can invite an user to your app by going on your Static Web App resource, going on the &lt;strong&gt;Role management&lt;/strong&gt; tab and clicking &lt;strong&gt;Invite&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1614230395012%2FeaqrNZ1QR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1614230395012%2FeaqrNZ1QR.png" alt="create invitation link.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now that the configuration files allow you to define which HTTP method you want your route definition to run, you can specify which of your HTTP methods will have authorization rules. There are more features that came with the new &lt;em&gt;staticwebapp.config.json&lt;/em&gt; file, some of them are really interesting! But I decided to focus this blog post on the authorization and HTTP methods part. You can read more about the new file &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/configuration" rel="noopener noreferrer"&gt;here&lt;/a&gt;. If you have any questions or feedback, let me know!&lt;/p&gt;

</description>
      <category>azurestaticwebapps</category>
      <category>azurefunctions</category>
      <category>azure</category>
      <category>staticwebapps</category>
    </item>
    <item>
      <title>Using function proxies with Azure Static Web Apps</title>
      <dc:creator>Daniel Reis</dc:creator>
      <pubDate>Fri, 19 Feb 2021 04:18:20 +0000</pubDate>
      <link>https://dev.to/danspark/using-function-proxies-with-azure-static-web-apps-njo</link>
      <guid>https://dev.to/danspark/using-function-proxies-with-azure-static-web-apps-njo</guid>
      <description>&lt;p&gt;&lt;a href="https://azure.microsoft.com/en-us/services/app-service/static/"&gt;Azure Static Web Apps&lt;/a&gt; is a service that provides you with a way to serve static content with an Azure Functions backend API. It's currently in preview, but it already looks promising, giving you a variety of useful features to build a web app. You can pull your code directly from GitHub, then Azure will add a GitHub Actions workflow to build and deploy to Azure Static Web Apps. It truly is a great service, and as of the day of writing this blog post, it's completely free, since it's on preview. You can read about all of Azure Static Web Apps features &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/overview#key-features"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The integrated API is a nice way to not worry about things like CORS, since it will be hosted on the same domain as the website on the &lt;code&gt;/api&lt;/code&gt; route. However, it currently imposes some limitations on what you can do with your function app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not every language is supported. You can only create your function app on JavaScript, C# and Python. This will probably be fixed in the future, as there's no good reason to not support other languages IMO.&lt;/li&gt;
&lt;li&gt;You can only add HTTP triggers. This one probably is going to remain this way, since it's purpose is to process requests from the frontend, but maybe I'm wrong. Input and output bindings works normally.&lt;/li&gt;
&lt;li&gt;Logs are only available through Application Insights. This means that you can't really troubleshoot the resource without creating an Application Insights resource along with your Static Web App. I'm not sure if this means that you cannot add other log providers through DI, but I'll investigate further later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that in mind, being limited to only HTTP triggers is not so bad, as you can use the Static Web App's function app as a proxy to other services using &lt;strong&gt;function proxies&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function Proxies
&lt;/h2&gt;

&lt;p&gt;Azure Function Proxies allow you to specify routes that will be implemented by another resource, with the option to override the HTTP method, the query string or the request headers. It's a pretty good tool for breaking a big service into smaller parts in a serverless architecture.&lt;/p&gt;

&lt;p&gt;To add a proxy to your function app, you just need to define a &lt;code&gt;proxies.json&lt;/code&gt; file on your project (Don't forget to copy the file to the build output!) and configure it according to your needs. This is how a proxies file look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://json.schemastore.org/proxies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"proxies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"&amp;lt;proxy-name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"matchCondition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/todo"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"backendUri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"%service-url%/api/todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"requestOverrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"backend.request.querystring.&amp;lt;querystring-name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-value"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"backend.request.header.&amp;lt;header-name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-value"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"responseOverrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"response.body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"response.statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"418"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The example above does some things that are worth explaining, we're doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a proxy with the name &lt;code&gt;&amp;lt;proxy-name&amp;gt;&lt;/code&gt; that will be triggered when the app receives a request on the &lt;code&gt;/api/todo&lt;/code&gt; route. You can also specify HTTP methods on the match condition.&lt;/li&gt;
&lt;li&gt;Setting the &lt;code&gt;backendUri&lt;/code&gt; to the service that implements our functionality. This is what will be called when the request matches the condition defined. &lt;code&gt;%service-url%&lt;/code&gt; is the syntax used for configuration (your &lt;code&gt;local.settings.json&lt;/code&gt; file or your environment variables).&lt;/li&gt;
&lt;li&gt;Overriding the request's &lt;code&gt;&amp;lt;header-name&amp;gt;&lt;/code&gt; header and &lt;code&gt;&amp;lt;querystring-name&amp;gt;&lt;/code&gt; query string key with the value 'example-value'.&lt;/li&gt;
&lt;li&gt;Overriding the response's body and status code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are more things that can be configured in your proxies file, you can read more about it &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-proxies#modify-requests-responses"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Function Proxies on SWAs
&lt;/h2&gt;

&lt;p&gt;Since SWA allows us to use its function app as a proxy, I made a static app that calls two other function apps through function proxies. This is how our services will communicate:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WCfJmBDN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613698087781/h5q44syBO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WCfJmBDN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613698087781/h5q44syBO.png" alt="azf-prx-swa.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code for this blog post is available on this GitHub repository:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/danielreis-dev"&gt;
        danielreis-dev
      &lt;/a&gt; / &lt;a href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps"&gt;
        function-proxies-on-static-web-apps
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Using Azure Functions proxies with Azure Static Web Apps
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Azure functions proxies with Azure Static Web Apps&lt;/h1&gt;
&lt;p&gt;This repository contains the sample app used in &lt;a href="https://blog.danielreis.dev/using-function-proxies-with-azure-static-web-apps" rel="nofollow"&gt;this blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Dependencies&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;.NET Core 3.1&lt;/li&gt;
&lt;li&gt;.NET 5&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Running the app&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://github.com/dotnet/tye"&gt;dotnet tye&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run the app with &lt;code&gt;tye run&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the dashboard on &lt;code&gt;http://localhost:8000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click the &lt;code&gt;frontend&lt;/code&gt; app's URL&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps/tree/master/catalog"&gt;Catalog Service&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This function app has one HTTP function that returns an array of catalog items. You can page the results by changing the &lt;code&gt;index&lt;/code&gt; value on the query string.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps/tree/master/orders"&gt;Orders Service&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This function app also has one HTTP function that return an order creation result. If you send any order item on the request, you'll receive a 200 OK with an order ID and a status. If you send an empty array, you'll receive a 400 BAD REQUEST.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps/tree/master/app"&gt;SWA Frontend&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is a Blazor WebAssembly app that allows you to browse through catalog items and add them to an in-memory shopping cart. After that, you can finish your shopping by creating an order. It also has a &lt;code&gt;routes.json&lt;/code&gt; configured to serve the same file (&lt;code&gt;index.html&lt;/code&gt;) on every route, this is required and you can read more about it  &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/deploy-blazor#fallback-route"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps/tree/master/bff"&gt;SWA Backend&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is a simple function app that includes a &lt;a href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps/blob/master/bff/proxies.json"&gt;&lt;code&gt;proxies.json&lt;/code&gt;&lt;/a&gt; file that maps to the two other function apps' &lt;code&gt;backendUri&lt;/code&gt; using environment variables (&lt;code&gt;%CONNECTIONSTRINGS__CATALOG%&lt;/code&gt; and &lt;code&gt;%CONNECTIONSTRINGS__ORDERS%&lt;/code&gt;). Both proxies override the query string's &lt;code&gt;code&lt;/code&gt; value to include the function app's function key that is required for authentication in production, we'll see how to set these values later on, but they're not required in your development environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Currently, you can't add configuration settings on a SWA that doesn't have any functions in it, so I also included a dummy HTTP function to allow configuration in production. I believe that it should be a valid scenario to only have proxies on your backend function app, so I created an &lt;a href="https://github.com/Azure/static-web-apps/issues/289"&gt;issue&lt;/a&gt; on the Static Web App's GitHub repository. I'll update this post with any info they provide me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On the  &lt;a href="https://github.com/danielreis-dev/function-proxies-on-static-web-apps/blob/master/bff/local.settings.json"&gt;&lt;code&gt;local.settings.json&lt;/code&gt;&lt;/a&gt; file, there are two &lt;strong&gt;important&lt;/strong&gt; settings that are worth explaining:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    "AZURE_FUNCTION_PROXY_DISABLE_LOCAL_CALL": true,
    "SERVICE__CATALOG__KEY": "catalog_key" ,
    "SERVICE__ORDERS__KEY": "orders_key"
  },
  "Host": {
    "CORS": "*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AZURE_FUNCTION_PROXY_DISABLE_LOCAL_CALL&lt;/code&gt;: For some reason, when calling your proxy in development gives an error saying that a recursive call was detected, even though it's correctly configured to call another function app listening in another port. Setting this variable to &lt;code&gt;true&lt;/code&gt; fixes the problem.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CORS:*&lt;/code&gt;: Since we're running this app locally, you'll receive an error if this setting is not present. That's because the Blazor app is running on a different port than the Backend function app. It will work correctly on production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Running the application
&lt;/h2&gt;

&lt;p&gt;To make testing easier, I've added a &lt;code&gt;tye.yaml&lt;/code&gt; file that spins up all four services with one command. It also gives us a nice dashboard with logs and other useful info about the running services. If you never heard about  &lt;a href="https://github.com/dotnet/tye"&gt;Tye&lt;/a&gt;, you should really check it out, it's a wonderful tool that helps a lot with the development of microservices, but all you need to know for now is how to install the tool (&lt;code&gt;dotnet tool install -g Microsoft.Tye --version "0.6.0-alpha.21070.5"&lt;/code&gt;) and run it (&lt;code&gt;tye run&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-store&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app/MyStore.App.csproj&lt;/span&gt;
  &lt;span class="na"&gt;bindings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bff&lt;/span&gt;
  &lt;span class="na"&gt;azureFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bff/&lt;/span&gt;
  &lt;span class="na"&gt;bindings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7070&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;catalog&lt;/span&gt;
  &lt;span class="na"&gt;azureFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;catalog/&lt;/span&gt;
  &lt;span class="na"&gt;bindings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
      &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${protocol}://${host}:${port}&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orders&lt;/span&gt;
  &lt;span class="na"&gt;azureFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orders/&lt;/span&gt;
  &lt;span class="na"&gt;bindings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
      &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${protocol}://${host}:${port}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The YAML file configures the SWA backend app to always run on the port 7070 and assign the other three services random ports. It also sets the environment variables required for the SWA backend to call the Orders and Catalog service, that happens through the &lt;code&gt;connectionString&lt;/code&gt; binding defined on the file. When running the command &lt;code&gt;tye run&lt;/code&gt;, you should see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KQlc9apU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613700895681/XtzaDw-_6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KQlc9apU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613700895681/XtzaDw-_6.png" alt="tye run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dashboard is hosted on &lt;code&gt;http://localhost:8000&lt;/code&gt;, it should list you all four services:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RV6ehPoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613701058509/ZpdG-hWvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RV6ehPoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613701058509/ZpdG-hWvp.png" alt="tye dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, when you access the frontend app, you should be able to add items to your card and finish your order!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_ngGj506e7w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: For some reason, requests going through the proxy always take &lt;strong&gt;at least&lt;/strong&gt; two seconds. Do not panic, as this does not seem to be happening in production.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Creating and configuring your Azure Static Web App
&lt;/h2&gt;

&lt;p&gt;Now that you've seen the app in action, it's time to deploy it to production and configure it. If you need instructions on how to create an Azure Static Web App, check out this Microsoft &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/get-started-portal"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now we need to configure our SWA function app and add our function keys and URLs. You can get the function key for each function app running the following commands on the &lt;a href="https://docs.microsoft.com/en-us/cli/azure/"&gt;Azure CLI&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp &lt;span class="k"&gt;function &lt;/span&gt;keys list &lt;span class="nt"&gt;-g&lt;/span&gt; &amp;lt;ResourceGroupName&amp;gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;CatalogFunctionAppName&amp;gt; &lt;span class="nt"&gt;--function-name&lt;/span&gt; get-catalog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp &lt;span class="k"&gt;function &lt;/span&gt;keys list &lt;span class="nt"&gt;-g&lt;/span&gt; &amp;lt;ResourceGroupName&amp;gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;OrdersFunctionAppName&amp;gt; &lt;span class="nt"&gt;--function-name&lt;/span&gt; create-order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These should be added in the Configuration section as &lt;code&gt;SERVICE__CATALOG__KEY&lt;/code&gt; and &lt;code&gt;SERVICE__ORDERS__KEY&lt;/code&gt;, respectively. As for the URLs, they should be add as &lt;code&gt;CONNECTIONSTRINGS__CATALOG&lt;/code&gt; and &lt;code&gt;CONNECTIONSTRINGS__ORDERS&lt;/code&gt;. You can get them using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp config &lt;span class="nb"&gt;hostname &lt;/span&gt;list &lt;span class="nt"&gt;-g&lt;/span&gt; &amp;lt;ResourceGroupName&amp;gt; &lt;span class="nt"&gt;--webapp-name&lt;/span&gt; &amp;lt;FunctionAppName&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After all that, your should be up and running, and your Configuration section should be looking like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xZuShV1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613704182443/iCXs8218W.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xZuShV1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1613704182443/iCXs8218W.png" alt="swa configuration section"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you found this post useful. Static Web Apps have amazing potential and I'm hopeful the service will only get better, if you have any questions or feedback, please let me know in the comments!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>azure</category>
      <category>dotnet</category>
      <category>azurestaticwebapps</category>
    </item>
  </channel>
</rss>
