chronoxor / NetCoreServer

Ultra fast and low latency asynchronous socket server & client C# .NET Core library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution
https://chronoxor.github.io/NetCoreServer
MIT License
2.63k stars 550 forks source link

Add cache to the parent directory of index.html in InsertPathInternal? #277

Closed vvyoko closed 9 months ago

vvyoko commented 9 months ago

First thanks for fixed the cache update issue

Accessing a directory to redirect to index.html under the directory is a very common behavior like http://localhost:7777/test/ --> http://localhost:7777/test/index.html

Redirects can be implemented in external code However, cache modification involves some private variables, which is difficult for external code to modify

        private bool InsertPathInternal(string root, string path, string prefix, TimeSpan timeout, InsertHandler handler)
        {
            try
            {
                // Iterate through all directory entries
                foreach (var item in Directory.GetDirectories(path))
                {
                    string key = prefix + "/" + HttpUtility.UrlDecode(Path.GetFileName(item));

                    // Recursively insert sub-directory
                    if (!InsertPathInternal(root, item, key, timeout, handler))
                        return false;
                }

                foreach (var item in Directory.GetFiles(path))
                {
                    string key = prefix + "/" + HttpUtility.UrlDecode(Path.GetFileName(item));

                    if (key.EndsWith("index.html", StringComparison.InvariantCultureIgnoreCase))
                    {
                        InsertFileInternal(root, item, key.Replace("index.html", "", StringComparison.InvariantCultureIgnoreCase), timeout, handler);
                    }
                    // Insert file into the cache
                    if (!InsertFileInternal(root, item, key, timeout, handler))
                        return false;
                }

                return true;
            }
            catch (Exception) { return false; }
        }

by the way,Is there a better way to redirect? Manually construct the response of 307 not work (ask gpt)

else if (request.Method == "GET")
{
    string key = request.Url;  //     /test
    key = Uri.UnescapeDataString(key);
    if (string.IsNullOrEmpty(Path.GetExtension(key)))
    {
        // not work
        //var response = Response.MakeOkResponse(307);
        //response.SetHeader("Location", key + "/index.html");
        //SendResponseAsync(response);

        var redirect = Cache.Find(key + "/");
        if (redirect.Item1)
        {
            SendResponseAsync(
                Response.MakeGetResponse(
                    Encoding.UTF8.GetBytes("<script>window.location=window.location.href+\"/\";</script>")));
        }
    }
}
chronoxor commented 9 months ago

This could be done in user code, not inside NetCoreServer library. In HttpsServer example this could be implemented like this:

    class HttpCacheSession : HttpSession
    {
        public HttpCacheSession(NetCoreServer.HttpServer server) : base(server) {}

        protected override void OnReceivedRequest(HttpRequest request)
        {
            if (request.Method == "GET")
            {
                if (request.Url == "/")
                {
                    var response = Cache.Find("/index.html");
                    if (response.Item1)
                        SendAsync(response.Item2);
                    else
                        SendResponseAsync(Response.MakeErrorResponse(404, "Cannot find index.html"));
                }
            }
            else
                SendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: " + request.Method));
        }
}        
vvyoko commented 9 months ago

thx,it work fine

string key = request.Url;
key = Uri.UnescapeDataString(key);
if (string.IsNullOrEmpty(Path.GetExtension(key)))
{
    if (key.EndsWith('/'))
    {
        var redirect = Cache.Find(key + "index.html");
        if (redirect.Item1)
        {
            SendAsync(redirect.Item2);
            return;
        }
    }
    else if (Cache.Find(key + "/index.html").Item1)
    {
        var r = Response.MakeOkResponse(307);
        r.SetBody(Encoding.UTF8.GetBytes("<script>window.location=window.location.href+\"/\";</script>").AsSpan());
        //r.SetHeader("Location", key + "/");
        SendResponseAsync(r);
        return;
    }
}