💬 #ChatGPT Plugin in NET – Map route handler for manifest file: ai-plugin.json
Tags: englishpost, chatgpt, net
Published: 2023-07-06 15:16:56

---
title: 💬 #ChatGPT Plugin in NET – Map route handler for manifest file: ai-plugin.json
published: true
date: 2023-06-30 14:49:53 UTC
tags: EnglishPost,ChatGPT,EnglishPost,NET
canonical_url: 
---

Hi!

The ChatGPT Plugin in NET is a fun side pet project. And hey, my goal is to share this with a fully functional Codespace, so everyone can test this without a local dev environment.

_Note: If you want to learn more about [Codespaces, check the official documentation here](https://docs.github.com/en/codespaces/overview)._

## Plugin File Manifest

Let’s review the [official documentation](https://platform.openai.com/docs/plugins/getting-started/plugin-manifest) about plugin file manifest:

_Every plugin requires a `ai-plugin.json` file, which needs to be hosted on the API’s domain. For example, a company called `example.com` would make the plugin JSON file accessible via an [https://example.com](https://example.com/) domain since that is where their API is hosted. When you install the plugin via the ChatGPT UI, on the backend we look for a file located at `/.well-known/ai-plugin.json`. The `/.well-known` folder is required and must exist on your domain in order for ChatGPT to connect with your plugin. If there is no file found, the plugin cannot be installed. For local development, you can use HTTP but if you are pointing to a remote server, HTTPS is required._

Super easy, however, we have a challenge with a single ai-plugin.json file that serves both; dev on local and dev on Codespaces.

## Dynamic Plugin File Manifest for Local and Codespaces dev environments

There are several ways to solve this problem. I like this one:

**_use route handlers for the ai-plugin.json request_**

Reading the Minimal API doc, the [Route Handlers in Minimal API apps](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/route-handlers?view=aspnetcore-7.0) section, I decided to give a try to a route handler that handles the ai-plugin.json request. In this request

We will get the current host for the API. Can be local dev, Codespaces dev or Production.

We will read the ai-plugin.json file and replace the $host variable with the current host value.

The handler will return the ai-plugin.json with the correct values.

This is the final code for this:

```csharp

// publish the plugin manifest information, update the host with the current one
app.MapGet("/.well-known/ai-plugin.json", (HttpRequest request) =>
{
    // get current url from request headers (codespaces dev) or app Urls (local dev)
    var userAgent = request.Headers.UserAgent;
    var customHeader = request. Headers["x-custom-header"];
    var currentUrl = request. Headers["x-forwarded-proto"] + "://" + request.Headers["x-forwarded-host"];
    if (currentUrl == "://")
        currentUrl = app.Urls.First();

    // update current host in manifest
    string aiPlugInManifest = File.ReadAllText("pluginInfo/ai-plugin.json");
    aiPlugInManifest = aiPlugInManifest.Replace("$host", currentUrl);
    return Results.Json(aiPlugInManifest);
})
.WithName(".well-known/ai-plugin.json")
.WithOpenApi(generatedOperation =>
{
    generatedOperation.Description = "Gets the plugin manifest information.";
    return generatedOperation;
});

```

And this is a sample of the ai-plugin.json file:

```json

{
  "schema_version": "v1",
  "name_for_human": "El Bruno Pet Search",
  "name_for_model": "elbrunopets",
  "description_for_human": "Search through El Bruno's wide range of pets and pets' owners.",
  "description_for_model": "Plugin for searching through El Bruno's pets. Use it whenever a user asks about pets or pets'owners.",
  "auth": {
    "type": "none"
  },
  "api": {
    "type": "openapi",
    "url": "$host/swagger/v1/swagger.yaml",
    "is_user_authenticated": false
  },
  "logo_url": "$host/pluginInfo/logo.png",
  "contact_email": "support@example.com",
  "legal_info_url": "http://www.example.com/legal"
}

```

Now, once the api is running, we can see the Swagger definition including this GET action.

![](https://brunocapuano.files.wordpress.com/2023/06/image-4.png?w=538)

And this is a sample of the expected output in localhost mode:

![](https://brunocapuano.files.wordpress.com/2023/06/image-5.png?w=915)

And in codespaces mode

![](https://brunocapuano.files.wordpress.com/2023/06/image-6.png?w=1024)

This is super cool. I’ll continue updating [the repo](https://github.com/elbruno/OpenAI-Plugin-NET-Sample) with the demo instructions, and a live session will be scheduled soon!

Happy coding!

Greetings

El Bruno

More posts in my blog [ElBruno.com](https://www.elbruno.com).

More info in [https://beacons.ai/elbruno](https://beacons.ai/elbruno)

* * *