url-shortener/UrlShortenerApp.cs

112 lines
3.3 KiB
C#

using HashidsNet;
using LiteDB;
using Tesses.WebServer;
namespace UrlShortener
{
internal class UrlShortenerApp : Server
{
private Config config;
private IHashids ids;
private ILiteCollection<UrlShortenEntry> Collection()
{
var database=new LiteDatabase(Path.Combine("data","database.db"));
return database.GetCollection<UrlShortenEntry>("Urls");
}
public UrlShortenerApp(Config config, IHashids ids)
{
this.config = config;
this.ids = ids;
}
public override async Task GetAsync(ServerContext ctx)
{
string id=ctx.UrlPath.Substring(1);
if(GetUrl(id,out var destUrl))
{
await ctx.SendRedirectAsync(destUrl);
}
else
{
await ctx.SendRedirectAsync(RelToRoot($"/404.html?id={id}"));
}
}
private bool GetUrl(string id, out string destUrl)
{
destUrl = "";
if(ids.TryDecodeSingleLong(id,out var idOut))
{
var col= Collection();
var item = col.FindById(idOut);
if(item != null)
{
destUrl = item.Url;
return true;
}
}
return false;
}
public string RelToRoot(string path)
{
return $"{config.UrlRoot.TrimEnd('/')}/{path.TrimStart('/')}";
}
internal void Run()
{
MountableServer server=new MountableServer(new StaticServer(Path.Combine("data","www")));
RouteServer api=new RouteServer();
server.Mount("/s/",this);
server.Mount("/api/v1/",api);
api.Add("/AddEntry",AddEntryAsync,"POST");
api.Add("/GetEntry",GetEntryAsync);
server.StartServer(config.Port);
}
private async Task GetEntryAsync(ServerContext ctx)
{
if(ctx.QueryParams.TryGetFirst("id",out var id))
{
if(ids.TryDecodeSingleLong(id,out var idOut))
{
var col= Collection();
var item = col.FindById(idOut);
if(item != null)
{
await ctx.SendJsonAsync(new{Url = item.Url, Success=true,Created=item.Created});
return;
}
}
}
await ctx.SendJsonAsync(new{Success = false});
}
private async Task AddEntryAsync(ServerContext ctx)
{
ctx.ParseBody();
if(ctx.QueryParams.TryGetFirst("url",out var url))
{
var itemLS=Collection();
var date = DateTime.Now;
var id=itemLS.Insert(new UrlShortenEntry(){Url = url,Created = date});
string id2=ids.EncodeLong(id.AsInt64);
await ctx.SendJsonAsync(new{
Success=true,
Url = RelToRoot($"/s/{id2}"),
Created = date,
Id = id2
});
}
else
{
await ctx.SendJsonAsync(new{Success = false});
}
}
}
}