2

I'm working on a project that requires a web server to listen for GET requests where the URL is structured as /function/JWT where /function is the command and /JWT is a JSON web token. Arguments about the security of this practice aside, that's how the sender is providing the data.

I was able to build out some of the other requirements for this project using the System.Net.HttpServer class, but I'm finding now that it limits URL segments to something like 260 characters before it returns a 400 server error. I can't be changing registries every time I deploy this utility, so it seems like I might have to try something else.

How can I use .NET core to launch a web server that will detect when /function is the start of the absolute path and hand the JWT off to other code for interpretation? Some of the example tokens I have are over 500 characters long and they may be more in other cases so I need the max URL segment length to be much longer. Despite hours of research on this I can't find a simple answer to this seemingly simple problem.

hunsbct
  • 31
  • 7
  • Instead of using a GET request, if you use a POST request, you will be able to pass the JWT in the POST body. – Balaji Kanagaraju May 20 '21 at 15:23
  • Are you using a ASP.Net Core self-hosted app? – phuzi May 20 '21 at 15:23
  • If your client's HTTP implementation is that broken, then you probably can't use a compliant service (like HttpServer). How about you write your own HttpServer class (it isn't that difficult)? – Neil May 20 '21 at 15:26
  • Seems this is a similar issue: https://stackoverflow.com/questions/42243211/increase-max-url-length-in-asp-net-core – phuzi May 20 '21 at 15:26
  • @phuzi No ASP involvement here, just a regular .NET core console app. – hunsbct May 20 '21 at 15:28
  • I'd recommend trying an ASP.Net Core self-hosted app using Kestrel as it doesn't use HTTP.sys that requires the registry hack/change. – phuzi May 20 '21 at 15:31
  • @Neil If necessary I could take a stab at it, but I'm rewriting/improving this project from an older Java implementation and it seems from what I can tell that it natively handled those GET requests without anything too special so I'd be surprised if that weren't possible in C#. – hunsbct May 20 '21 at 15:32
  • @phuzi Thanks, I'll check that out. – hunsbct May 20 '21 at 15:32
  • BTW, it can be hosted in a regular console app too. – phuzi May 20 '21 at 15:32
  • 1
    Just created a new .Net 5 ASP.Net Core app running in console and confirmed that it can handle URL segments in excess of 5,000 characters. – phuzi May 20 '21 at 15:50

1 Answers1

3

Using a self-hosted ASP.NET Core app (i.e., not fronted by IIS or another reverse proxy with its own limit):

The MaxRequestLineSize for Kestrel defaults to 8192 bytes, and can be configured to a greater length if required:

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureKestrel(serverOptions =>
                    {
                        serverOptions.Limits.MaxRequestLineSize = 16000;
                    })
                    .UseStartup<Startup>();
                });
    }

And then you can simply configure an endpoint to handle the function/ route:

 public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // 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();
            }


            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/function/{jwt}", async context =>
                {
                    var jwt = (string)context.Request.RouteValues["jwt"];
                    await context.Response.WriteAsync($"JWT is {jwt}, Length is {jwt.Length}");
                });
            });
        }
    }
Eric Munn
  • 580
  • 2
  • 8
  • This is exactly what I needed! I've been using C# for years but this is my first venture into asp.net projects so I greatly appreciate your help in getting things started. Looking forward to building on this example. – hunsbct May 20 '21 at 17:50