Skip to content

Instantly share code, notes, and snippets.

@thegabriele97
Last active March 3, 2020 11:14
Show Gist options
  • Save thegabriele97/18140583fdb4a5488456dd317b431275 to your computer and use it in GitHub Desktop.
Save thegabriele97/18140583fdb4a5488456dd317b431275 to your computer and use it in GitHub Desktop.
[C#] Middleware for saving http pages in a SQL DB, with regex filter and autoremove. Exceptions handling included
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"RegisterPageMiddleware": {
"excluded": [
"^\\/css\\/(.*)$",
"^\\/lib\\/(.*)$",
"^\\/js\\/(.*)$",
"^(.*)favicon\\.ico"
]
}
}
CREATE TABLE [dbo].[PageUrls]
(
[PageId] INT NOT NULL IDENTITY(1,1),
[PageUrl] VARCHAR(250) NOT NULL,
PRIMARY KEY ([PageUrl])
)
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.SqlClient;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using System.Text.RegularExpressions;
namespace WebApplication2.Middlewares {
public class RegisterPageMiddleware {
private readonly ILogger<RegisterPageMiddleware> _logger;
private readonly IConfiguration _config;
private readonly RequestDelegate _next;
public RegisterPageMiddleware(RequestDelegate next, ILogger<RegisterPageMiddleware> logger, IConfiguration config) {
_logger = logger;
_config = config;
_next = next;
}
public async Task InvokeAsync(HttpContext context) {
int excludedPathsCount = 0;
var path = context.Request.Path.Value;
try {
excludedPathsCount = _config
.GetSection("RegisterPageMiddleware")
.GetSection("excluded")
.Get<List<string>>()
.Select(e => new Regex(e))
.Count(r => r.IsMatch(path));
} catch (ArgumentNullException) {
_logger.LogWarning("RegisterPageMiddleware/excluded must contains at least one element (like \"\")");
excludedPathsCount = 0;
}
if (excludedPathsCount > 0) {
using (var connection = new SqlConnection(_config.GetConnectionString("DefaultConnection"))) {
await connection.OpenAsync();
var query = "DELETE FROM dbo.PageUrls WHERE PageUrl = @path";
using (var command = new SqlCommand(query, connection)) {
command.Parameters.AddWithValue("@path", path);
if ((await command.ExecuteNonQueryAsync()) > 0) {
_logger.LogInformation($"MATCH WITH REGEX: URL removed {path}");
}
}
}
await _next(context);
return; //The current {path} is a match with regex in appsettings.json so it will be excluded
}
using (var connection = new SqlConnection(_config.GetConnectionString("DefaultConnection"))) {
await connection.OpenAsync();
var query = "SELECT * FROM dbo.PageUrls WHERE PageUrl = @path";
using (var command = new SqlCommand(query, connection)) {
command.Parameters.AddWithValue("@path", path);
using (var reader = await command.ExecuteReaderAsync()) {
if (reader.HasRows) {
await _next(context);
return; //The page {path} is already registered in the db; so do nothing
}
}
}
query = "INSERT INTO dbo.PageUrls (PageUrl) VALUES (@path)";
using (var command = new SqlCommand(query, connection)) {
command.Parameters.AddWithValue("@path", path);
if ((await command.ExecuteNonQueryAsync()) > 0) {
_logger.LogInformation($"New URL registered: {path}");
}
}
}
await _next(context);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using WebApplication2.Middlewares;
namespace WebApplication2 {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//REGISTER THE MIDDLEWARE HERE
app.UseMiddleware<RegisterPageMiddleware>();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment