microsoft / GraphEngine

Microsoft Graph Engine
http://www.graphengine.io/
MIT License
2.19k stars 328 forks source link

[Feature Request] Ability to return a TSL service API definition as a Swagger.json file #340

Closed mwherman2000 closed 2 years ago

mwherman2000 commented 2 years ago

The changes would need to take place somewhere near this method in the code-generated HTTP.cs file...

        public static void ListAvailableEndpoints(HttpListenerContext ctx, IEnumerable<string> availableEndpointNames, Type serverType)
        {
            string text = ctx.Request.Url.GetLeftPart(UriPartial.Authority);
            if (typeof(CommunicationModule).IsAssignableFrom(serverType))
            {
                int num = ctx.Request.RawUrl.IndexOf('/', 1);
                if (num >= 0)
                {
                    string str = ctx.Request.RawUrl.Substring(1, num - 1);
                    text = text + "/" + str;
                }
            }

            string text2 = Serializer.ToString(GenerateDefaultHttpHandlerResponseObject(text, availableEndpointNames, serverType));
            using (StreamWriter streamWriter = new StreamWriter(ctx.Response.OutputStream))
            {
                if (ctx.Request.AcceptTypes != null && !ctx.Request.AcceptTypes.Contains("application/json"))
                {
                    ctx.Response.ContentType = "text/html";
                    using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Trinity.Network.Http.index.html"))
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            string text3 = streamReader.ReadToEnd();
                            streamWriter.WriteLine(text3.Replace("//%AVAILABLE_ENDPOINTS%", "var available_endpoints = " + text2 + ";"));
                        }
                    }
                }
                else
                {
                    ctx.Response.ContentType = "application/json";
                    streamWriter.WriteLine(text2);
                }
            }
        }

...and/or where this method is called in the same HTTP.cs file...

        /// <summary>
        /// Processes requests on the root endpoint. By default it
        /// will list available API endpoints in html.
        /// Override this method to get custom behaviors.
        /// </summary>
        /// <param name="ctx">A <see cref="HttpListenerContext"/> object.</param>
        protected override void RootHttpHandler(HttpListenerContext ctx)
        {
            CommonHttpHandlers.ListAvailableEndpoints(ctx, s_HttpHandlerLookupTable.Keys, this.GetType());
        }
mwherman2000 commented 2 years ago

It turns out that

  1. the above RootHttpHandler() is overridable in the implementation class for your GE server, and
  2. it's actually the generic HTTP handler method that is called for every URL that you haven't defined a protocol REST endpoint for.

The implication is that by overriding RootHttpHandler(), your GE server can support any custom URLs you need (e.g. http://localhost:8081/v2/swagger.json). Here's the skeleton code you need in your GE server implementation class:

        protected override void RootHttpHandler(HttpListenerContext ctx)
        {
            Debug.WriteLine("RootHttpHandler <<<<");
            if (ctx.Request.RawUrl.ToLower() == "/v2/swagger.json")
            {
                using (StreamWriter streamWriter = new StreamWriter(ctx.Response.OutputStream))
                {
                    streamWriter.WriteLine("<html><body><h3>TODO: Generate Swagger API Definition</h3></body></html>");
                }
                ctx.Response.StatusCode = 200;
            }
            else
            {
                base.RootHttpHandler(ctx);
            }
        }
mwherman2000 commented 2 years ago

Will update this as I make progress on the actual Swagger implementation.