Base solution for your next web application
Open Closed

Add a folder for API documentation - independent of ASP.NET Zero app #11779


User avatar
0
hongbing.wang created

The requirement: “API documentation should be available from a folder/url within WMS Pro (e.g. /apidoc). This folder would serve as the root folder for the API documentation, so that it can be filled out with multiple pages and resources independent of the main WMS Pro app.”

Our Zero app's server and angular client are within the same application. We aim to incorporate a folder for HTML documentation for APIs, allowing access from outside the Zero web app.

I’ve created a new folder under \server\wwwroot\apidoc.

Initial attempt in Configure() of Startup.cs (in ASP.NET Core):

`#if HTTPONLY_COOKIE && RELEASE app.Use(async (context, next) => { if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith("/apidoc")) { // Rewrite the request to remove the '/apidoc' prefix context.Request.Path = context.Request.Path.Value.Substring("/apidoc".Length); await next(); } else { await next(); } });

        app.UseStaticFiles(); // Assuming this middleware is for serving static files

        app.Use(async (context, next) =>
        {
            if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
            {
                context.Request.Path = "/index.html";
                await next();
            }
        });

#endif`

FYI: The existing code was: `#if HTTPONLY_COOKIE && RELEASE app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) { context.Request.Path = "/index.html"; await next(); } }); #endif

        app.UseStaticFiles();`

The problem: "\apidoc" was always redirected by the ‘catch all’ route of the angular app. The intended ASP.NET Core rewrite didn't work as expected.

Please advise how to resolve the issue.

Thank you for your support.


3 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @hongbing.wang

    I think instead of using a middleware like below, it would be easier to create a new controller and return apidoc file in this controller's action. You can use Route attribute to set any route for this api documentation.

    if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith("/apidoc"))
    {
        // code blocks
    }
    
  • User Avatar
    0
    hongbing.wang created

    Hi @ismcagdas, Thank you for your suggestion. Please have a look at my implementation of ApiDocController below. Am I on the right track? I can see that the attribute routing works for the existing TokenAuthController. I think in this case I don't need to do anything special to enable attribute routing, right? I haven't got it working. Please point out what is missed. Thank you.

    `namespace umsplus.Web.Controllers { [Route("apidoc")] public class ApiDocController : umsplusControllerBase { public ApiDocController() {

        }
    
        [HttpGet("{fileName}")]
        public IActionResult GetFile(string fileName)
        {
            // Assuming your apidoc files are stored in the wwwroot/apidoc directory
            // Validate and sanitize fileName
            fileName = Path.GetFileNameWithoutExtension(fileName) + Path.GetExtension(fileName); // Remove potential path traversal attempts
    
            // Enforce directory restriction
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "apidoc", fileName);
            filePath = Path.GetFullPath(filePath); // Normalize path
    
            if (filePath.StartsWith(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "apidoc")))
            {
                // Proceed with file retrieval if path is valid
                if (System.IO.File.Exists(filePath))
                {
                    var fileContent = System.IO.File.ReadAllBytes(filePath);
                    return File(fileContent, "application/octet-stream", fileName);
                }
                else
                {
                    return NotFound();
                }
            }
            else
            {
                // Handle invalid path attempts, potentially logging or raising an alert
                return BadRequest("Invalid file path");
            }
        }
    }
    

    }`

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @hongbing.wang

    Yes, this seems correct. Could you send an email to [email protected] and share

    1. A sample URL which should work
    2. File for the URL to test

    Thanks,