112 lines
3.3 KiB
C#
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});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|