using HashidsNet; using LiteDB; using Tesses.WebServer; namespace UrlShortener { internal class UrlShortenerApp : Server { private Config config; private IHashids ids; private ILiteCollection Collection() { var database=new LiteDatabase(Path.Combine("data","database.db")); return database.GetCollection("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}); } } } }